Поскольку вы используете 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 |