将多个sql行与不同的列组合在一起

时间:2013-06-13 13:08:38

标签: c# sql

好的,所以说我有这样的事情:

ID | Name | Address
 1 | Bob  | 123 Fake Street
 1 | Bob  | 221 Other Street

通过执行以下操作完成:

select p.ID, p.Name a.Address from People p 
inner join Addresses a on a.OwnerID = p.ID

有没有办法把它变成

ID | Name |    Address_1    |     Address_2    | etc...
 1 | Bob  | 123 Fake Street | 221 Other street | etc

我看过在一列中用逗号分隔值的东西,但我不希望我想要不同的列。我使用MSSQL和C#查询这个我不知道是否会改变任何东西。此外,这是一个与我正在做的类似的场景,因此无法更改表的实际结构。

有人有任何建议吗?

1 个答案:

答案 0 :(得分:4)

您可以使用PIVOT功能获取结果,但您还必须使用row_number()实施,这样您就可以将每个人的多个地址转换为列。

如果您有已知数量的地址,那么您将对查询进行硬编码:

select id, name, address_1, address_2
from
(
  select p.id, p.name, a.address,
    'Address_'+cast(row_number() over(partition by p.id 
                                      order by a.ownerid) as varchar(10)) rn
  from people p
  inner join addresses a
    on p.id = a.ownerid
) d
pivot
(
  max(address)
  for rn in (address_1, address_2)
) piv;

请参阅SQL Fiddle with Demo

但是如果是你的情况,那么每个人的地址数量都是未知的,因此你需要使用动态SQL并将其放入存储过程来执行:

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT distinct ',' + QUOTENAME('Address_'+d.rn) 
                    from 
                    (
                      select cast(row_number() over(partition by a.ownerid
                                      order by a.ownerid) as varchar(10)) rn
                      from Addresses a
                    ) d
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT id, name, ' + @cols + ' 
            from
            (
              select p.id, p.name, a.address,
                ''Address_''+cast(row_number() over(partition by p.id 
                                                  order by a.ownerid) as varchar(10)) rn
              from people p
              inner join addresses a
                on p.id = a.ownerid
            ) d
            pivot 
            (
                max(address)
                for rn in (' + @cols + ')
            ) p '

execute(@query);

SQL Fiddle with Demo。这些都给出了结果:

| ID | NAME |         ADDRESS_1 |        ADDRESS_2 | ADDRESS_3 |
----------------------------------------------------------------
|  1 |  Bob |   123 Fake Street | 221 Other Street |    (null) |
|  2 |  Jim | 123 e main street |           (null) |    (null) |
|  3 |  Tim |   489 North Drive |   56 June Street |  415 Lost |