Dus*_*sht 1 sql sql-server pivot unpivot
我有以下来自我的SQL查询的结果:
Id atr1 atr2 atr3 atr4
1 a bsdf csdfs djk
5 esdds f gds hkkj
8 i j ksd lk
9 ads sdf dfse wer
Run Code Online (Sandbox Code Playgroud)
现在我需要以下格式的上述结果:
S.no 1 2 3 4
Id 1 5 8 9
atr1 a esdds i ads
atr2 bsdf f j sdf
atr3 csdfs gds ksd dfse
atr4 djk hkkj lk wer
Run Code Online (Sandbox Code Playgroud)
我无法用Pivot和Unpivot做到这一点.
为了获得您想要的最终结果,您需要取消当前列的显示,然后应用pivot功能.但在您对数据进行取消/ row_number()转移之前,我建议您使用为每行生成唯一值.
您可以通过几种不同的方式获得结果,包括使用带有CASE表达式的聚合函数,静态PIVOT和动态PIVOT.
使用CASE聚合:您可以通过首先使用UNION ALL查询将多列转换为行来获取结果,然后使用带有CASE表达式的聚合函数:
;with cte as
(
select id, atr1, atr2, atr3, atr4,
row_number() over(order by id) seq
from yourtable
)
select s_no,
max(case when seq = 1 then value end) [1],
max(case when seq = 2 then value end) [2],
max(case when seq = 3 then value end) [3],
max(case when seq = 4 then value end) [4]
from
(
select seq, s_no = 'id', value = cast(id as varchar(5)), so = 1
from cte
union all
select seq, s_no = 'atr1', value = atr1, so = 2
from cte
union all
select seq, s_no = 'atr2', value = atr2, so = 3
from cte
union all
select seq, s_no = 'atr3', value = atr3, so = 4
from cte
union all
select seq, s_no = 'atr4', value = atr4, so = 5
from cte
) d
group by s_no, so
order by so;
Run Code Online (Sandbox Code Playgroud)
静态UNPIVOT/PIVOT:如果您想要转换的数量有限,则可以对查询进行硬编码.逆透视的过程将您的多个列转换id,atr1,atr2,atr3,和atr4,并将其转换为多行.您没有指定正在使用的SQL Server版本,但可以使用该UNPIVOT功能或使用CROSS APPLY.
select seq, s_no, value, so
from
(
select id, atr1, atr2, atr3, atr4,
row_number() over(order by id) seq
from yourtable
) s
cross apply
(
select 'id', cast(id as varchar(5)), 1 union all
select 'atr1', atr1, 2 union all
select 'atr2', atr2, 3 union all
select 'atr3', atr3, 4 union all
select 'atr4', atr4, 5
) c (s_no, value, so);
Run Code Online (Sandbox Code Playgroud)
请参阅SQL Fiddle with Demo.我使用CROSS APPLY和UNION ALL来选择每个列并将它们转换为多行.此查询将使您的数据采用以下格式:
| SEQ | S_NO | VALUE | SO |
| 1 | id | 1 | 1 |
| 1 | atr1 | a | 2 |
| 1 | atr2 | bsdf | 3 |
| 1 | atr3 | csdfs | 4 |
| 1 | atr4 | djk | 5 |
| 2 | id | 5 | 1 |
Run Code Online (Sandbox Code Playgroud)
将数据放入多行后,即可应用PIVOT函数:
select s_no, [1], [2], [3], [4]
from
(
select seq, s_no, value, so
from
(
select id, atr1, atr2, atr3, atr4,
row_number() over(order by id) seq
from yourtable
) s
cross apply
(
select 'id', cast(id as varchar(5)), 1 union all
select 'atr1', atr1, 2 union all
select 'atr2', atr2, 3 union all
select 'atr3', atr3, 4 union all
select 'atr4', atr4, 5
) c (s_no, value, so)
) d
pivot
(
max(value)
for seq in ([1], [2], [3], [4])
) piv
order by so;
Run Code Online (Sandbox Code Playgroud)
动态UNPIVOT/PIVOT: 如果您想要创建已知或有限数量的新列,但如果您有未知数量的值要转换为列,则上述工作非常有用,那么您将需要查看使用动态SQL.这将生成一个sql字符串,然后执行该字符串以获得最终结果:
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT ',' + QUOTENAME(seq)
from
(
select row_number() over(order by id) seq
from yourtable
)d
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT s_no,' + @cols + '
from
(
select seq, s_no, value, so
from
(
select id, atr1, atr2, atr3, atr4,
row_number() over(order by id) seq
from yourtable
) s
cross apply
(
select ''id'', cast(id as varchar(5)), 1 union all
select ''atr1'', atr1, 2 union all
select ''atr2'', atr2, 3 union all
select ''atr3'', atr3, 4 union all
select ''atr4'', atr4, 5
) c (s_no, value, so)
) x
pivot
(
max(value)
for seq in (' + @cols + ')
) p '
execute sp_executesql @query;
Run Code Online (Sandbox Code Playgroud)
请参阅SQL Fiddle with Demo.所有版本都会给出结果:
| S_NO | 1 | 2 | 3 | 4 |
| id | 1 | 5 | 8 | 9 |
| atr1 | a | esdds | i | ads |
| atr2 | bsdf | f | j | sdf |
| atr3 | csdfs | gds | ksd | dfse |
| atr4 | djk | hkkj | lk | wer |
Run Code Online (Sandbox Code Playgroud)