如何使用两个支点
How to use two pivot
我有 3 个表:
1) 用户
id name
1 abc
1 abc
2 tyu
2 tyu
2) phone
id number
1 0987654
1 0890764
2 3445667
2 5643456
3) 地址
id addr type
1 usa 1
1 uae 1
2 Uk 2
所以现在我写了下面的查询:
select * from (
select u.id, u.name , p.number, cs.COL + CAST(row_number()over(PARTITION BY u.ID ORDER BY cs.COL) AS VARCHAR) RN ,
cs1.COL + CAST(row_number()over(PARTITION BY a.ID ORDER BY cs1.COL) AS VARCHAR) RN1
,a.addr
from user u left join phone p on p.id = u.id
left join address as a on a.id = p.id CROSS APPLY (VALUES ('phone',number)) CS(Col,val)
CROSS APPLY (VALUES ('add',a.addr)) CS1(Col,val)
where u.id=1 and a.type = '1'
)P
PIVOT (MAX(number) FOR RN IN ([phone1],[phone2])) as pivot1
PIVOT (MAX(addr1) FOR RN1 IN ([add1],[add2])) as pivot2
所以上面的查询给我的输出如下:
id name phone1 phone2 add1 add2
1 abc NULL 0987654 NULL usa
1 abc 0890764 NULL uae NULL
但我想要如下输出:
id name phone1 phone2 add1 add2
1 abc 0890764 0987654 uae usa
那么我怎样才能用枢轴实现这个呢?
在转置之前,您需要将数据设置为稍微不同的格式。
您的思路是正确的,但是将列 RN 和 RN1 合并为一个,然后 pvioting 同时对它们进行操作 - 如下所示。
select id, name, [phone1], [phone2], [add1], [add2]
from (
select u.id, u.name, pa.columnname, pa.value from
user u inner join
(
select id, number as value, 'phone' + cast(row_number() over(partition by id order by number) as char(1)) as columnname
from phone
union all
select id, addr, 'add' + cast(row_number() over(partition by id order by addr) as char(1)) as columnname
from address where type = 1
) as pa
on pa.id = u.id
) as base
pivot (max(value) for columnname in ([phone1], [phone2], [add1], [add2])) p
where id = 1;
declare @user TABLE
(id int, name varchar(3))
;
INSERT INTO @user
(id, name)
VALUES
(1, 'abc'),
(1, 'abc'),
(2, 'tyu'),
(2, 'tyu')
;
declare @phone TABLE
(id int, number int)
;
INSERT INTO @phone
(id, number)
VALUES
(1, 0987654),
(1, 0890764),
(2, 3445667),
(2, 5643456)
;
declare @address TABLE
(id int, addr varchar(3), type int)
;
INSERT INTO @address
(id, addr, type)
VALUES
(1, 'usa', 1),
(1, 'uae', 1),
(2, 'Uk', 2)
;
select id,name,MAX(phone1)phone1,max(phone2)phone2,max(add1)add1,max(add2)add2 from (
select u.id, u.name , p.number, cs.COL + CAST(row_number()over(PARTITION BY u.ID ORDER BY cs.COL) AS VARCHAR) RN ,
cs1.COL + CAST(row_number()over(PARTITION BY a.ID ORDER BY cs1.COL) AS VARCHAR) RN1
,a.addr
from @user u left join @phone p on p.id = u.id
left join @address as a on a.id = p.id CROSS APPLY (VALUES ('phone',number)) CS(Col,val)
CROSS APPLY (VALUES ('add',a.addr)) CS1(Col,val)
where u.id=1 and a.type = '1'
)P
PIVOT (MAX(number) FOR RN IN ([phone1],[phone2])) as pivot1
PIVOT (MAX(addr) FOR RN1 IN ([add1],[add2])) as pivot2
group by id,name
我有 3 个表:
1) 用户
id name
1 abc
1 abc
2 tyu
2 tyu
2) phone
id number
1 0987654
1 0890764
2 3445667
2 5643456
3) 地址
id addr type
1 usa 1
1 uae 1
2 Uk 2
所以现在我写了下面的查询:
select * from (
select u.id, u.name , p.number, cs.COL + CAST(row_number()over(PARTITION BY u.ID ORDER BY cs.COL) AS VARCHAR) RN ,
cs1.COL + CAST(row_number()over(PARTITION BY a.ID ORDER BY cs1.COL) AS VARCHAR) RN1
,a.addr
from user u left join phone p on p.id = u.id
left join address as a on a.id = p.id CROSS APPLY (VALUES ('phone',number)) CS(Col,val)
CROSS APPLY (VALUES ('add',a.addr)) CS1(Col,val)
where u.id=1 and a.type = '1'
)P
PIVOT (MAX(number) FOR RN IN ([phone1],[phone2])) as pivot1
PIVOT (MAX(addr1) FOR RN1 IN ([add1],[add2])) as pivot2
所以上面的查询给我的输出如下:
id name phone1 phone2 add1 add2
1 abc NULL 0987654 NULL usa
1 abc 0890764 NULL uae NULL
但我想要如下输出:
id name phone1 phone2 add1 add2
1 abc 0890764 0987654 uae usa
那么我怎样才能用枢轴实现这个呢?
在转置之前,您需要将数据设置为稍微不同的格式。 您的思路是正确的,但是将列 RN 和 RN1 合并为一个,然后 pvioting 同时对它们进行操作 - 如下所示。
select id, name, [phone1], [phone2], [add1], [add2]
from (
select u.id, u.name, pa.columnname, pa.value from
user u inner join
(
select id, number as value, 'phone' + cast(row_number() over(partition by id order by number) as char(1)) as columnname
from phone
union all
select id, addr, 'add' + cast(row_number() over(partition by id order by addr) as char(1)) as columnname
from address where type = 1
) as pa
on pa.id = u.id
) as base
pivot (max(value) for columnname in ([phone1], [phone2], [add1], [add2])) p
where id = 1;
declare @user TABLE
(id int, name varchar(3))
;
INSERT INTO @user
(id, name)
VALUES
(1, 'abc'),
(1, 'abc'),
(2, 'tyu'),
(2, 'tyu')
;
declare @phone TABLE
(id int, number int)
;
INSERT INTO @phone
(id, number)
VALUES
(1, 0987654),
(1, 0890764),
(2, 3445667),
(2, 5643456)
;
declare @address TABLE
(id int, addr varchar(3), type int)
;
INSERT INTO @address
(id, addr, type)
VALUES
(1, 'usa', 1),
(1, 'uae', 1),
(2, 'Uk', 2)
;
select id,name,MAX(phone1)phone1,max(phone2)phone2,max(add1)add1,max(add2)add2 from (
select u.id, u.name , p.number, cs.COL + CAST(row_number()over(PARTITION BY u.ID ORDER BY cs.COL) AS VARCHAR) RN ,
cs1.COL + CAST(row_number()over(PARTITION BY a.ID ORDER BY cs1.COL) AS VARCHAR) RN1
,a.addr
from @user u left join @phone p on p.id = u.id
left join @address as a on a.id = p.id CROSS APPLY (VALUES ('phone',number)) CS(Col,val)
CROSS APPLY (VALUES ('add',a.addr)) CS1(Col,val)
where u.id=1 and a.type = '1'
)P
PIVOT (MAX(number) FOR RN IN ([phone1],[phone2])) as pivot1
PIVOT (MAX(addr) FOR RN1 IN ([add1],[add2])) as pivot2
group by id,name