SQL Как объединить два столбца данных в разные столбцы? - PullRequest
3 голосов
/ 28 июня 2019

У меня есть таблица:

| 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, но дублировал его как для выручки, так и для выручки2?

Спасибо

EDIT: испортил выходную таблицу, на которую я надеялся! Я отредактировал фактическую выходную таблицу, которую хочу увидеть!

РЕДАКТИРОВАТЬ 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    |

Ответы [ 2 ]

8 голосов
/ 28 июня 2019

Мое предложение всегда состоит в том, чтобы сначала написать свой запрос в виде жестко запрограммированной или статической версии, прежде чем погрузиться в динамический 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 )

0 голосов
/ 28 июня 2019

Сделайте это с 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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...