1

我在可视化地址信息时遇到问题。

例子

  • 我有 1 个人或关系有超过 1 个地址。
  • 我将每个地址存储在地址表中并定义它是什么类型的地址。
  • 例如,我有 3 种地址类型。

我需要做的是可视化所有相邻的地址列。

如果我只有一个地址,则必须显示其他字段,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

这就是结果的样子:

在此处输入图像描述

4

1 回答 1

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;

请参阅SQL Fiddle with Demo

您可以同时应用UNPIVOTPIVOT函数。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 |
于 2013-07-12T22:15:59.500 回答