SQL按联接分组

SQL按联接分组,sql,sql-server,join,group-by,Sql,Sql Server,Join,Group By,我需要加入三个表来说明产品需要哪些文档。并非每个产品都需要所有文档 有一个文档表、一个产品表和一个DocTracking表,用于跟踪与产品关联的文档 Product Table ProdID ProdName 1 Ball 2 Wheel 产品表 ProdID ProdName 1个球 2轮 篡改表 ProdID DocID 1 1 1 2 2 2 我希望联接如下所示: ProdID ProdName

我需要加入三个表来说明产品需要哪些文档。并非每个产品都需要所有文档

有一个文档表、一个产品表和一个DocTracking表,用于跟踪与产品关联的文档

Product Table ProdID ProdName 1 Ball 2 Wheel 产品表 ProdID ProdName 1个球 2轮 篡改表 ProdID DocID 1 1 1 2 2 2 我希望联接如下所示:

ProdID ProdName Needs Word Doc? Needs Excel Doc? 1 Ball Yes Yes 2 Wheel No Yes ProdID ProdName需要Word文档吗?需要Excel文档吗? 1个球是的是的 2轮否是
如果我需要将其转换为存储过程,任何帮助都将不胜感激

如果您只有这些文档,并且它们已修复,则可以使用此查询:

SELECT ProdID, ProdName,      
       [Needs Word Doc] = CASE WHEN EXISTS(
           SELECT 1 FROM Document  d INNER JOIN DocTracking dt ON d.DocID=dt.DocID
           WHERE dt.ProdID = p.ProdID AND d.[Doc Name] = 'Word Document'
       ) THEN 'Yes' ELSE 'No' END,
       [Needs Excel Doc] = CASE WHEN EXISTS(
           SELECT 1 FROM Document  d INNER JOIN DocTracking dt ON d.DocID=dt.DocID
           WHERE dt.ProdID = p.ProdID AND d.[Doc Name] = ' Excel Spreadsheet'
       ) THEN 'Yes' ELSE 'No' END
FROM dbo.Product  p

当然,您也可以使用
DocID
,这样查询就不依赖于名称

这比典型的pivot查询稍微复杂一点。但是,唯一具有挑战性的部分是确定包含哪些文档,然后将
'Yes'
'No'
输出

select P.ProdID, P.ProdName, 
       case 
          when DW.DocID is null then 'Yes'
          else 'No' 
       end as NeedsWordDoc,    
       case 
          when DE.DocID is null then 'Yes'
          else 'No' 
       end as NeedsExcelDoc
from Product P
left join DocTracking DTW on DTW.ProdId = P.ProdId
left join Document DW on DW.DocID = DTW.DocID
                          and DW.Name = 'Word Document'
left join DocTracking DTE on DTE.ProdId = P.ProdId
left join Document DE on DE.DocID = DTE.DocID
                          and DE.Name = 'Excel Spreadsheet'
下面使用
coalesce()
和一个检查是否存在一种文档类型的条件来执行此操作:

select pt.ProdId, pt.ProdName,
       coalesce(MAX(case when dt.DocId = 1 then 'Yes' end), 'No') as "Needs Word Doc?",
       coalesce(MAX(case when dt.DocId = 2 then 'Yes' end), 'No') as "Needs Excel Doc?"
from ProductTable pt left outer join
     DocTracking dt 
     on dt.ProdId = dt.ProdId
group by pt.ProdId, pt.ProdName;

请注意,SQL查询返回固定数量的列。因此,不能让SQL查询仅根据documents表中的内容返回不同数量的列。您可以在字符串中创建SQL查询,然后使用特定于数据库的命令来运行它。

这可能会对您有所帮助-使用pivot:

select ProdId, ProdName, 
case when isnull([Word Document],0)<>0 then 'Yes'
else 'No' 
end as  [Needs Word Doc?],
case when isnull([Excel Spreadsheet],0)<>0 then 'Yes'
else 'No' 
end as  [Needs Excel Spreadsheet?]
 from
(
select p.ProdId,p.ProdName,d.DocId,d.DocName from 
@Prod p left join 
@Track t
on p.ProdId=t.ProdId 
inner join @Doc d
on t.DocId=d.DocId
)
as temp
pivot
(max(DocID)
For DocName in ([Word Document],[Excel Spreadsheet])
)
as pvt
选择ProdId,ProdName,
如果isnull([Word文档],0)0,则为“是”
否则“不”
结束为[需要Word文档?],
如果为空([Excel电子表格],0)0,则为“是”
否则“不”
结束为[需要Excel电子表格?]
从…起
(
从中选择p.ProdId、p.ProdName、d.DocId、d.DocName
@Prod p左连接
@轨道t
在p.ProdId=t.ProdId上
内部连接@Doc d
在t.DocId=d.DocId上
)
临时工
支点
(最大值(DocID)
用于([Word文档]、[Excel电子表格])中的文档名
)
作为pvt

在此处搜索“数据透视表”,以此类推。你也可以用案例陈述来做。谢谢你的评论。不幸的是,“现实生活”中大约有20个文档,而且它不是固定的,将来可能会有更多。我现在只想说这个,但是如果有人有更好的方法,请告诉我。我听说不使用游标,但似乎是时候使用它了?
select ProdId, ProdName, 
case when isnull([Word Document],0)<>0 then 'Yes'
else 'No' 
end as  [Needs Word Doc?],
case when isnull([Excel Spreadsheet],0)<>0 then 'Yes'
else 'No' 
end as  [Needs Excel Spreadsheet?]
 from
(
select p.ProdId,p.ProdName,d.DocId,d.DocName from 
@Prod p left join 
@Track t
on p.ProdId=t.ProdId 
inner join @Doc d
on t.DocId=d.DocId
)
as temp
pivot
(max(DocID)
For DocName in ([Word Document],[Excel Spreadsheet])
)
as pvt