我正在尝试使用动态数据透视,并需要将行转换为列的帮助
表格如下:
ID expense revenue date
1 43 45 12-31-2012
1 32 32 01-01-2013
3 64 56 01-31-2013
4 31 32 02-31-2013
我需要报告目的,如
ID expense12-31-2012 expense01-01-2013 expense01-31-2013 revenue12-31-2013
1 43 32
3 64
答案 0 :(得分:2)
为了将expense
和revenue
列作为date
的标题,我建议同时应用UNPIVOT和PIVOT函数。
UNPIVOT会将费用和收入列转换为您可以追加日期的行。将日期添加到列名称后,即可应用PIVOT功能。
UNPIVOT代码将是:
select id,
col+'_'+convert(varchar(10), date, 110) new_col,
value
from yt
unpivot
(
value
for col in (expense, revenue)
) un
见SQL Fiddle with Demo。这会产生一个结果:
| ID | NEW_COL | VALUE |
-----------------------------------
| 1 | expense_12-31-2012 | 43 |
| 1 | revenue_12-31-2012 | 45 |
| 2 | expense_01-01-2013 | 32 |
正如您所看到的,费用/收入列现在是通过将日期连接到结尾而创建的new_col
行。然后在PIVOT中使用此new_col
:
select id,
[expense_12-31-2012], [revenue_12-31-2012],
[expense_01-01-2013], [revenue_01-01-2013],
[expense_01-31-2013], [revenue_01-31-2013],
[expense_03-03-2013], [revenue_03-03-2013]
from
(
select id,
col+'_'+convert(varchar(10), date, 110) new_col,
value
from yt
unpivot
(
value
for col in (expense, revenue)
) un
) src
pivot
(
sum(value)
for new_col in ([expense_12-31-2012], [revenue_12-31-2012],
[expense_01-01-2013], [revenue_01-01-2013],
[expense_01-31-2013], [revenue_01-31-2013],
[expense_03-03-2013], [revenue_03-03-2013])
) piv;
如果你有一个已知数量的日期变成列,但如果你有一个未知数量的日期,那么上面的版本将会很好用,那么你将需要使用动态SQL来生成结果:
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT ',' + QUOTENAME(c.col+'_'+convert(varchar(10), yt.date, 110))
from yt
cross apply
(
select 'expense' col union all
select 'revenue'
) c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT id,' + @cols + '
from
(
select id,
col+''_''+convert(varchar(10), date, 110) new_col,
value
from yt
unpivot
(
value
for col in (expense, revenue)
) un
) src
pivot
(
sum(value)
for new_col in (' + @cols + ')
) p '
execute(@query);
见SQL Fiddle with Demo。两个查询都会生成相同的结果。