我的地址表如下
CREATE TABLE ADDRESS
(
PERSON_ID INT,
ADDRESSLINE1 VARCHAR(100),
CITY VARCHAR(100)
)
表中数据如下
INSERT INTO ADDRESS
VALUES (1, 'Street 1', 'CITY1'), (1, 'Street 2', 'CITY1'),
(1, 'Street 3', 'CITY1'),
(2, 'Street 1', 'CITY2'), (2, 'Street 2', 'CITY2'),
(2, 'Street 3', 'CITY3'),
(3, 'Street 1', 'CITY3'), (3, 'Street 2', 'CITY3')
我需要编写一个SQL查询,该查询以以下格式返回输出
PERSON_ID ADDRESS1 ADDRESS2 ADDRESS3
------------------------------------------------------------------------
1 'Street 1 CITY1' 'Street 2 CITY1' 'Street 3 CITY1'
2 'Street 1 CITY2' 'Street 2 CITY2' 'Street 3 CITY2'
3 'Street 1 CITY3' 'Street 2 CITY3'
地址数据(ADDRESSLINE1和CITY)需要串联为一个值,并且结果集中表中的每一行都应具有一列。数据需要根据PERSON_ID分组
这可以使用SQL语句完成吗?
答案 0 :(得分:0)
CREATE TABLE ADDRESS(
PERSON_ID INT,
ADDRESSLINE1 VARCHAR(100),
CITY VARCHAR(100))
INSERT INTO ADDRESS VALUES(1,'STREET 1','CITY1')
INSERT INTO ADDRESS VALUES(1,'STREET 2','CITY1')
INSERT INTO ADDRESS VALUES(1,'STREET 3','CITY1')
INSERT INTO ADDRESS VALUES(2,'STREET 1','CITY2')
INSERT INTO ADDRESS VALUES(2,'STREET 2','CITY2')
INSERT INTO ADDRESS VALUES(2,'STREET 3','CITY3')
INSERT INTO ADDRESS VALUES(3,'STREET 1','CITY3')
INSERT INTO ADDRESS VALUES(3,'STREET 2','CITY3')
SELECT PERSON_ID, MAX(CASE WHEN ADDRESSLINE1='STREET 1' THEN CONCAT(ADDRESSLINE1,' ',CITY) ELSE '' END) ADDRESS1 ,
MAX(CASE WHEN ADDRESSLINE1='STREET 2' THEN CONCAT(ADDRESSLINE1,' ',CITY) ELSE '' END) ADDRESS2 ,
MAX(CASE WHEN ADDRESSLINE1='STREET 3' THEN CONCAT(ADDRESSLINE1,' ',CITY) ELSE '' END) ADDRESS3 FROM ADDRESS
GROUP BY PERSON_ID
output
PERSON_ID ADDRESS1 ADDRESS2 ADDRESS3
1 'STREET 1 CITY1' 'STREET 2 CITY1' 'STREET 3 CITY1'
2 'STREET 1 CITY2' 'STREET 2 CITY2' 'STREET 3 CITY2'
3 'STREET 1 CITY3' 'STREET 2 CITY3'
答案 1 :(得分:0)
这将为您解决问题-我使用了动态数据透视来解决。
NB:已将您的Addressline1更改为在表上命名为Addressline
NB2:这是动态的,这意味着我计算一个ID有多少个外观。如果一个ID上有4个外观,那么您将获得4列地址行。
CREATE TABLE ADDRESS(
PERSON_ID INT,
ADDRESSLINE VARCHAR(100),
CITY VARCHAR(100))
DECLARE @Str NVARCHAR(MAX);
DECLARE @Str2 NVARCHAR(MAX);
SELECT @Str = STUFF(
(
SELECT DISTINCT
','+QUOTENAME(Addresses)
FROM (
select 'Addressline'+cast(n as varchar(50)) as Addresses from (select max(totalcountaddresses) as TotalAddresses from (select COUNT(*) as TotalCountAddresses from dbo.address
group by person_id
)x
)o
cross apply (
select n from
(select ROW_NUMBER() over(PARTITION by name order by (select null)) as n from master..spt_values where type='p'
)z
where n <= o.TotalAddresses
)y
)t
FOR XML PATH('')
), 1, 1, '');
-- PRINT @Str
SET @str2 = N'
select * from (
select AddressLine,Person_Id,''Addressline''+cast(rn as varchar(50)) as Adr from (
select Addressline+ '' '' +city as Addressline,Person_id,ROW_NUMBER() over(PARTITION by Person_id order by addressline) as rn
from dbo.address
)z
)x
PIVOT
(Max(Addressline) FOR adr in ('+@Str+')
) as p';
--PRINT @Str2;
EXEC (@Str2);
结果
答案 2 :(得分:0)
您可以将此设置为PIVOT。
技巧是使用ROW_NUMBER生成PIVOT的列名称。
SELECT *
FROM
(
SELECT
PERSON_ID,
CONCAT(ADDRESSLINE1,' ',CITY) AS ADDRESS_CITY,
CONCAT('ADDRESS',ROW_NUMBER() OVER (PARTITION BY PERSON_ID ORDER BY ADDRESSLINE1)) AS COL
FROM ADDRESS
) SRC
PIVOT
(
MAX([ADDRESS_CITY])
FOR COL IN ([ADDRESS1],[ADDRESS2],[ADDRESS3])
) AS PVT
ORDER BY PERSON_ID;
要以动态Sql方式执行此操作,最多需要42个ADDRESS列:
declare @Cols varchar(535);
declare @MaxTotalAddresses INT = (select top 1 count(*) from ADDRESS group by PERSON_ID order by count(*) desc);
;with RCTE as
(
select 1 as n
union all
select n + 1 from RCTE where n < @MaxTotalAddresses
)
select @Cols = concat(@Cols + ', ', quotename(concat('ADDRESS',n)))
from RCTE;
declare @DynSql varchar(1000);
set @DynSql = 'SELECT *
FROM
(
SELECT
PERSON_ID,
CONCAT(ADDRESSLINE1,'' ''+CITY) AS ADDRESS_CITY,
CONCAT(''ADDRESS'',ROW_NUMBER() OVER (PARTITION BY PERSON_ID ORDER BY ADDRESSLINE1)) AS COL
FROM ADDRESS
) SRC
PIVOT
(
MAX([ADDRESS_CITY])
FOR COL IN ('+ @Cols +')
) AS PVT
ORDER BY PERSON_ID';
--select @DynSql as DynSql;
exec(@DynSql);