为了将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
是通过将日期连接到末尾而创建的行。然后new_col
在 PIVOT 中使用它:
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 Fiddle with Demo。
如果您有已知数量的日期要转换为列,则上述版本将非常有用,但如果您有未知数量的日期,那么您将需要使用动态 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。两个查询生成相同的结果。