SQL如何将两列数据转换为不同的列?

dig*_*doo 3 sql sql-server pivot

这是我的桌子:

| Scheme Code | MonthYear | Revenue | Revenue2 |
|-------------|-----------|---------|----------|
| 18VDA       | 2018.1    | 100     | 50       |
| 18VDA       | 2018.2    | 200     | 100      |
| 18VDA       | 2018.3    | 200     | 150      |
Run Code Online (Sandbox Code Playgroud)

我想将其设置为:

| 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      |
Run Code Online (Sandbox Code Playgroud)

我该如何做才能使其在MonthYear中枢转,但可以同时复制收入和收入2?

谢谢

编辑:弄乱了我希望的输出表!我已经编辑了想要查看的实际输出表!

编辑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);
Run Code Online (Sandbox Code Playgroud)

我编写的这段代码仅对一列进行操作,并且得到如下输出:

| Scheme Code | 2018.1 | 2018.2 | 2018.3 |
|-------------|--------|--------|--------|
| 18VDA       | 100    | 200    | 200    |
Run Code Online (Sandbox Code Playgroud)

Tar*_*ryn 8

我的建议总是尝试在进入动态SQL之前先将您的查询编写为硬编码或静态版本。这样一来,您可以使用较小的数据子集获得所需的最终结果,并且可以验证逻辑是否正确。

我将通过先执行UNPIVOTRevenue列中的一篇来解决此问题,然后再看一下应用该PIVOT功能。To UNPIVOT既可以使用UNPIVOT函数,也可以CROSS APPLY与a 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;
Run Code Online (Sandbox Code Playgroud)

您会注意到,CROSS APPLY我在中添加了带有A或的列,B用于标识RevenueRevenue2列。然后用于创建的新列名称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;
Run Code Online (Sandbox Code Playgroud)

两者都应产生相同的结果(dbfiddle demo