我的数据类似于以下
Set Cost Times
----------------------------
GHT 100 20
GHA 80 30
GHE 70 10
有时会有更多行,有时会有更少行。使用上面的示例,我想要撤回的内容类似于:
Col1 Col2 Col3 Col4 Col5 Col6 Col7 Col8 Col9
-----------------------------------------------------------------------------
GHT 100 20 GHA 80 30 GHE 70 10
提前致谢
JJ
答案 0 :(得分:2)
由于您将返回未知数量的行,因此您需要实现动态SQL以获取结果。您还需要同时取消3列,然后应用PIVOT将行转换回列,这将是一个两步过程。
由于您关心使用SQL Server 2005+,您可以使用CROSS APPLY来取消数据的移动,您会注意到我也使用row_number()
,因此当返回到列时,数据行仍然组合在一起。 UNPIVOT数据的代码类似于:
select col+'_'+cast(rn as varchar(50)) col,
value
from
(
select [set] as st, cost, times,
row_number() over(order by (select 1)) rn
from yourtable
) d
cross apply
(
values
('set', st),
('cost', cast(cost as varchar(50))),
('times', cast(times as varchar(50)))
) c (col, value);
见Demo。这会将数据转换为以下格式:
| COL | VALUE |
-------------------
| set_1 | GHT |
| cost_1 | 100 |
| times_1 | 20 |
一旦数据在多行中,您就可以应用PIVOT。动态SQL代码类似于以下内容:
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT ',' + QUOTENAME(col+'_'+cast(rn as varchar(50)))
from
(
select row_number() over(order by (select 1)) rn
from yourtable
) d
cross apply
(
select 'set', 1 union all
select 'cost', 2 union all
select 'times', 3
) c (col, so)
group by col, rn, so
order by rn, so
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT ' + @cols + '
from
(
select col+''_''+cast(rn as varchar(50)) col,
value
from
(
select [set], cost, times,
row_number() over(order by (select 1)) rn
from yourtable
) d
cross apply
(
values
(''set'', [set]),
(''cost'', cast(cost as varchar(50))),
(''times'', cast(times as varchar(50)))
) c (col, value)
) x
pivot
(
max(value)
for col in (' + @cols + ')
) p '
execute(@query);
见SQL Fiddle with Demo。这给出了一个结果:
| SET_1 | COST_1 | TIMES_1 | SET_2 | COST_2 | TIMES_2 | SET_3 | COST_3 | TIMES_3 |
----------------------------------------------------------------------------------
| GHT | 100 | 20 | GHA | 80 | 30 | GHE | 70 | 10 |