这是我的桌子:
| Scheme Code | MonthYear | Revenue | Revenue2 |
|-------------|-----------|---------|----------|
| 18VDA | 2018.1 | 100 | 50 |
| 18VDA | 2018.2 | 200 | 100 |
| 18VDA | 2018.3 | 200 | 150 |
我想将其设置为这样:
| Scheme Code | 2018.1 A | 2018.2 A | 2018.3 A | 2018.1 B | 2018.2 B | 2018.3 B |
|-------------|----------|----------|----------|----------|----------|----------|
| 18VDA | 100 | 200 | 200 | 50 | 100 | 150 |
我该如何做才能使其在MonthYear中枢转,但它会同时复制Revenue和Revenue2?
谢谢
编辑:弄乱了我希望的输出表!我已经编辑了要查看的实际输出表!
编辑2:
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
Select @cols = STUFF((SELECT ',' + QUOTENAME([MonthYear])
from tableA
group by [MonthYear]
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT *
FROM ( SELECT [Scheme Code], MonthYear ,[Revenue]
FROM TableA
) a
PIVOT(sum(Revenue) for MonthYear in (' + @cols + ')
) as RevenueMonth
ORDER BY [Scheme Code]'
execute(@query);
我编写的这段代码仅会执行一列,并且我得到的输出如下:
| Scheme Code | 2018.1 | 2018.2 | 2018.3 |
|-------------|--------|--------|--------|
| 18VDA | 100 | 200 | 200 |
答案 0 :(得分:8)
我的建议总是尝试在进入动态SQL之前先将您的查询写为硬编码或静态版本。这样,您可以使用较小的数据子集获得所需的最终结果,并且可以验证逻辑是否正确。
我将通过首先执行两个UNPIVOT
列中的Revenue
,然后考虑应用PIVOT
函数来解决这个问题。要使用UNPIVOT
,可以使用UNPIVOT
函数,也可以将CROSS APPLY
与UNION ALL
一起使用,以将两个Revenue
列转换为一个列。该查询的静态版本类似于以下内容:
select *
from
(
select
t.[Scheme Code],
new_colname = concat(t.[MonthYear], ' ', r.colname),
r.colvalue
from yourtable t
cross apply
(
select 'A', Revenue union all
select 'B', Revenue2
) r (colname, colvalue)
) d
pivot
(
sum(colvalue)
for new_colname in ([2018.1 A], [2018.2 A], [2018.3 A], [2018.1 B], [2018.2 B], [2018.3 B])
) p;
您会注意到,在CROSS APPLY
中,我添加了带有A
或B
的列,用于标识Revenue
或Revenue2
列。然后将其用于为PIVOT
创建新的列名。
这应该生成您想要的结果。现在要动态地执行此操作,您只需要将SQL转换为动态代码即可。您可以使用以下方法获得结果:
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
Select @cols = STUFF((SELECT ',' + QUOTENAME(concat([MonthYear], x.col))
from yourtable
cross join (select col = ' A' union all select ' B') x
group by [MonthYear], x.col
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT *
FROM
(
select
t.[Scheme Code],
new_colname = concat(t.[MonthYear], '' '', r.colname),
r.colvalue
from yourtable t
cross apply
(
select ''A'', Revenue union all
select ''B'', Revenue2
) r (colname, colvalue)
) a
PIVOT
(
sum(colvalue) for new_colname in (' + @cols + ')
) as x
ORDER BY [Scheme Code]';
exec sp_executesql @query;
这两种方法都应产生相同的结果(dbfiddle demo)
答案 1 :(得分:0)
使用CASE
和动态sql来完成。
DECLARE @colsA AS NVARCHAR(MAX),
@colsB AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @colsA = (SELECT ', sum(case [MonthYear] when ''' + [MonthYear] + ''' then Revenue end)' + QUOTENAME([MonthYear] + ' A')
from tableA
group by [MonthYear]
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'),
@colsB = (SELECT ', sum(case [MonthYear] when ''' + [MonthYear] + ''' then Revenue2 end)' + QUOTENAME([MonthYear] + ' B')
from tableA
group by [MonthYear]
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)');
Set @query = 'select [Scheme Code]' + @colsA + @colsB + ' from TableA group by [Scheme Code] order by [Scheme Code];';
print @query;