由于您使用的是 SQL Server,因此您可以通过多种方式将数据行转换为列。
您可以将聚合函数与 CASE 表达式一起使用:
select r.pkid,
r.name,
max(case when at.typedescription = 'home' then a.street end) homestreet,
max(case when at.typedescription = 'home' then a.number end) homeNumber,
max(case when at.typedescription = 'home' then a.zipcode end) homezipcode,
max(case when at.typedescription = 'home' then a.location end) homelocation,
max(case when at.typedescription = 'work' then a.street end) workstreet,
max(case when at.typedescription = 'work' then a.number end) workNumber,
max(case when at.typedescription = 'work' then a.zipcode end) workzipcode,
max(case when at.typedescription = 'work' then a.location end) worklocation,
max(case when at.typedescription = 'extra' then a.street end) extrastreet,
max(case when at.typedescription = 'extra' then a.number end) extraNumber,
max(case when at.typedescription = 'extra' then a.zipcode end) extrazipcode,
max(case when at.typedescription = 'extra' then a.location end) extralocation
from relation r
left join RelationXAdres ra
on r.pkid = ra.RelationID
left join adres a
on ra.adresid = a.pkid
left join adrestype at
on a.AdresTypeId = at.PKid
group by r.pkid, r.name;
请参阅SQL Fiddle with Demo。
您可以同时应用UNPIVOT和PIVOT函数。UNPIVOT 函数将获取您的多列street
, number
,zipcode
并将location
它们转换为多行。
select pkid, name,
col = typeDescription+col,
value
from
(
select r.pkid,
r.name,
at.typedescription,
a.street,
a.number,
a.zipcode,
a.location
from relation r
left join RelationXAdres ra
on r.pkid = ra.RelationID
left join adres a
on ra.adresid = a.pkid
left join adrestype at
on a.AdresTypeId = at.PKid
) d
unpivot
(
value
for col in (street, number, zipcode, location)
) unpiv;
请参阅SQL Fiddle with Demo。这给出了多行的结果:
| PKID | NAME | COL | VALUE |
-----------------------------------------------
| 1 | Peter | Workstreet | Streetname |
| 1 | Peter | Worknumber | 125 |
| 1 | Peter | Workzipcode | 5520 |
| 1 | Peter | Worklocation | Gent |
| 1 | Peter | Homestreet | StreetLane |
| 1 | Peter | Homenumber | 15 |
一旦数据位于多行中,您就可以应用 PIVOT 函数:
;with cte as
(
select pkid, name,
col = typeDescription+col,
value
from
(
select r.pkid,
r.name,
at.typedescription,
a.street,
a.number,
a.zipcode,
a.location
from relation r
left join RelationXAdres ra
on r.pkid = ra.RelationID
left join adres a
on ra.adresid = a.pkid
left join adrestype at
on a.AdresTypeId = at.PKid
) d
unpivot
(
value
for col in (street, number, zipcode, location)
) unpiv
)
select pkid, name,
homestreet, homenumber, homezipcode, homelocation,
workstreet, worknumber, workzipcode, worklocation,
extrastreet, extranumber, extrazipcode, extralocation
from cte
pivot
(
max(value)
for col in (homestreet, homenumber, homezipcode, homelocation,
workstreet, worknumber, workzipcode, worklocation,
extrastreet, extranumber, extrazipcode, extralocation)
) p;
请参阅SQL Fiddle with Demo。
如果您有已知数量的列,上述版本会很好用,但如果您有未知数量的值(地址类型),那么您将需要使用动态 SQL:
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT ',' + QUOTENAME(a.TypeDescription+c.col)
from Adrestype a
cross apply
(
select 'street', 1 union all
select 'number', 2 union all
select 'zipcode', 3 union all
select 'location', 4
) c (col, so)
group by a.TypeDescription, c.col, c.so
order by case a.TypeDescription
when 'home' then 1
when 'work' then 2
when 'extra' then 3 end, c.so
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT pkid, name, ' + @cols + '
from
(
select pkid, name,
col = typeDescription+col,
value
from
(
select r.pkid,
r.name,
at.typedescription,
a.street,
a.number,
a.zipcode,
a.location
from relation r
left join RelationXAdres ra
on r.pkid = ra.RelationID
left join adres a
on ra.adresid = a.pkid
left join adrestype at
on a.AdresTypeId = at.PKid
) d
unpivot
(
value
for col in (street, number, zipcode, location)
) unpiv
) x
pivot
(
max(value)
for col in (' + @cols + ')
) p '
execute sp_executesql @query;
请参阅SQL Fiddle with Demo。所有这些查询都会给出结果:
| PKID | NAME | HOMESTREET | HOMENUMBER | HOMEZIPCODE | HOMELOCATION | WORKSTREET | WORKNUMBER | WORKZIPCODE | WORKLOCATION | EXTRASTREET | EXTRANUMBER | EXTRAZIPCODE | EXTRALOCATION |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| 1 | Peter | StreetLane | 15 | 5550 | Rome | Streetname | 125 | 5520 | Gent | Street | 12 | 5120 | Paris |
| 2 | Nico | some Street | 12 | 2220 | Praag | againstraat | 5 | 4420 | Oslo | (null) | (null) | (null) | (null) |
| 3 | Bart | (null) | (null) | (null) | (null) | SoloStreet | 5 | 4420 | Oslo | (null) | (null) | (null) | (null) |
| 4 | Werner | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) | MainStreet | 25 | 1120 | Berlin |