在一行上显示相关实体的多行结果

时间:2014-12-03 15:14:58

标签: sql sql-server sql-server-2008

我有这个简化的表结构:

enter image description here

如果我执行此标准查询

SELECT p.Name as ProductName, ppl.Name as PersonName, pp.[Priority]
FROM Product p
    INNER JOIN ProductPeople pp ON pp.IdProduct = p.Id
    INNER JOIN People ppl ON pp.IdPerson = ppl.Id

我得到了这个结果:

enter image description here

但是我希望得到这样的结果:

enter image description here

对此有什么疑问?

谢谢!

2 个答案:

答案 0 :(得分:1)

您需要从ProductPeople INNER JOIN People中选择两次才能将它们放在同一行:

SELECT p.Name as [ProductName],
       ppl1.Name as [PersonPriority1],
       ppl2.Name as [PersonPriority2]
FROM Product p
INNER JOIN ProductPeople pp1
        ON pp1.IdProduct = p.Id
        AND pp1.[Priority] = 1
INNER JOIN People ppl1
        ON pp1.IdPerson = ppl1.Id
INNER JOIN ProductPeople pp2
        ON pp2.IdProduct = p.Id
        AND pp2.[Priority] = 2
INNER JOIN People ppl2
        ON pp2.IdPerson = ppl2.Id;

以上假设将始终存在Priority2 Person。如果该假设无效并且有ProductPeople个记录没有分配Priority2 Person,那么这将过滤掉整个行。在这种情况下,您需要在第二个参考上使用LEFT JOIN

SELECT p.Name as [ProductName],
       ppl1.Name as [PersonPriority1],
       ppl2.Name as [PersonPriority2]
FROM Product p
INNER JOIN ProductPeople pp1
        ON pp1.IdProduct = p.Id
        AND pp1.[Priority] = 1
INNER JOIN People ppl1
        ON pp1.IdPerson = ppl1.Id
LEFT JOIN (
              ProductPeople pp2
   INNER JOIN People ppl2
           ON pp2.IdPerson = ppl2.Id
          )
       ON pp2.IdProduct = p.Id
      AND pp2.[Priority] = 2;

答案 1 :(得分:1)

尝试以下方法:

declare @product table (Id int, Name varchar(100))
insert into @product select 1, 'Product 1' union select 2, 'Product 2'

declare @ProductPeople table(IdProduct int, IdPerson int, Priority int)
insert into @ProductPeople
select 1, 1, 1 union select 1, 2, 2 union select 2, 1, 1 union select 2, 2, 2

declare @People table(Id int, Name varchar(100))
insert into @People select 1, 'Person1' union select 2, 'Person2'

select ProductName, [1] 'PersonPriority1', [2] 'PersonPriority2'
from
(
select pd.Name as ProductName, ppl.Name, pp.Priority from @People ppl
join @ProductPeople pp on pp.IdPerson = ppl.Id
join @product pd on pd.Id = pp.IdProduct
)t
pivot 
(
max(Name) for priority in ([1], [2]))pvt