我在查看地址信息方面遇到了问题。
示例
我需要做的是将彼此相邻的所有地址列可视化。
如果我只有一个地址,则其他字段必须显示NULL
,因为没有地址。
我在这里创建了一个小表设置。
Create table relation(
PKid int identity(1,1) primary key,
Name varchar(255)
)
--Create table Adrestype(
PKid int identity(1,1) primary key,
TypeDescription varchar(255)
)
Create table adres(
PKid int identity(1,1) primary key,
Street varchar(255),
Number varchar(255),
zipcode varchar(255),
Location varchar(255),
AdresTypeId int
)
Create table RelationXAdres(
PKid int identity(1,1) primary key,
RelationID int not null,
adresID int not null
)
Insert into Relation values('Peter');
Insert into Relation values('Nico');
Insert into Relation values('Bart');
Insert into Relation values('Werner');
Insert into Adrestype values('Work');
Insert into Adrestype values('Home');
Insert into Adrestype values('Extra');
Insert into adres values ('Streetname', '125', '5520', 'Gent', 1)
Insert into adres values ('StreetLane', '15', '5550', 'Rome', 2)
Insert into adres values ('Street', '12', '5120', 'Paris', 3)
Insert into RelationXAdres values( 1,1);
Insert into RelationXAdres values( 1,2);
Insert into RelationXAdres values( 1,3);
Insert into adres values ('againstraat', '5', '4420', 'Oslo', 1)
Insert into adres values ('some Street', '12', '2220', 'Praag', 2)
Insert into RelationXAdres values( 2,4);
Insert into RelationXAdres values( 2,5);
Insert into adres values ('SoloStreet', '5', '4420', 'Oslo', 1)
Insert into RelationXAdres values( 3,6);
Insert into adres values ('MainStreet', '25', '1120', 'Berlin', 3)
Insert into RelationXAdres values( 4,7);
-- show all tabel's data
select * from relation
Select * from adres
select * from RelationXAdres
select * from Adrestype
-- Show all data in 1 statement
select * from relation r
left join RelationXAdres ra on ra.RelationID = r.PKid
left join adres a on a.PKid = ra.adresId
left join adrestype at on at.PKid = a.AdresTypeId
结果必须如下:
答案 0 :(得分:2)
由于您使用的是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;
您可以同时应用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:
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 |