好的,所以说我有这样的事情:
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#查询这个我不知道是否会改变任何东西。此外,这是一个与我正在做的类似的场景,因此无法更改表的实际结构。
有人有任何建议吗?
答案 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并将其放入存储过程来执行:
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 |