2013-07-22 3 views
1

У меня есть три таблицы, которые мне нужно для того, чтобы рассказать, какие документы нужны продукту. Не все документы необходимы для каждого продукта.SQL Group By Присоединиться

Существует таблица документов, таблица товаров и таблица DocTracking, которая отслеживает документы, связанные с продуктами

 
Product Table 
ProdID ProdName 
1  Ball 
2  Wheel 
 
DocTracking Table 
ProdID  DocID 
1   1 
1   2 
2   2 

Я хочу присоединиться выглядеть следующим образом:

 
ProdID  ProdName Needs Word Doc? Needs Excel Doc? 
1   Ball  Yes    Yes 
2   Wheel  No     Yes 

Любая помощь будет оценена, если мне нужно сделать это в Хранимой процедуре, это нормально.

+1

для поиска «сводной таблицы» здесь на SO. Вы также можете сделать это с помощью операторов Case. – Tim

ответ

1

Если у вас есть только те документы, и они исправить вы можете использовать этот запрос:

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, то запрос не зависит от имени.

+0

Спасибо за ваш комментарий. К сожалению, в «реальной жизни» есть около 20 документов, и это не исправлено, может быть больше по дороге. – NwkProg

+0

Я сейчас собираюсь пойти с этим, но если у кого-то есть лучший способ, дайте мне знать. Я слышал, чтобы не использовать курсоры, но, похоже, время использовать его? – NwkProg

1
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' 
1

Это немного сложнее, чем типичный сводный запрос. Но единственной сложной частью является определение, какие документы включены, а затем получение 'Yes' или 'No'.

Следующие делает это с 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-запрос, который просто возвращает другое количество столбцов на основе того, что присутствует в таблице документов. Вы можете создать SQL-запрос в строке, а затем использовать команду для конкретной базы данных для ее запуска.

0

может быть, это поможет вам - с помощью шарнира:

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