Распределить таблицу данных по двум столбцам, SQL-сервер - PullRequest
0 голосов
/ 25 января 2019

У меня есть таблица, которую я хотел бы изменить, в настоящее время она выглядит следующим образом:

ID    Year    Channel    Payments
 1    2012         HV         100
 1    2014         HV          56
 2    2012         NL       17000
 2    2012         HV         495
 3    2013         HV         565

и т. Д. С большим количеством строк.

Мне нужно изменить формуданные, так что есть одна строка для каждого идентификатора и несколько столбцов, показывающих платежи в каждом году и канале.Например, приведенная выше таблица будет выглядеть следующим образом:

ID   HV2012   HV2013   HV2014   NL2012
 1      100     NULL       56     NULL
 2      495     NULL     NULL    17000
 3     NULL      565     NULL     NULL

В прошлом мне удавалось сделать это довольно легко, используя dplyr в R, но теперь нужно использовать SQL-сервер.Я не смог найти способ сделать это без указания названий каждого нового столбца - поскольку мои данные охватывают многие каналы и годы, это нереально.Я понимаю, что для этого может потребоваться динамический SQL, но у меня нет опыта его использования.

Спасибо

Ответы [ 2 ]

0 голосов
/ 25 января 2019

Вы можете найти аналогичный запрос, который будет выполняться и в более низкой версии SQL Server.

-- query
DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX);

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(Channel + Convert(Varchar(4) ,Year))
            FROM testTable c
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT Id, ' + @cols + ' from 
            (
                select Id, Payments,
                Channel + Convert(Varchar(4) ,Year) NewCol
                from testTable
           ) x
            pivot 
            (
                 max(Payments)
                for NewCol in (' + @cols + ')
            ) p '

execute(@query)

Здесь вы можете найти живую демонстрацию .

РЕДАКТИРОВАТЬ

Чтобы сохранить данные во временной таблице, вы можете попробовать следующий запрос.

create table MyTable
(
    Id int,
    Year int,
    Channel varchar(10),
    Payments int
)

insert into MyTable values 
               (1,2012,'HV',100),
               (1,2014,'HV',56),
               (2,2012,'NL',17000),
               (2,2012,'HV',495), 
               (3,2013,'HV',565)


Declare @SQL varchar(max) = '    
if object_id(''##TestTable'') is not null
begin
    drop table ##TestTable
end

create table ##TestTable([Id] int null, ' + 
            Stuff((Select Distinct ','+QuoteName(Channel + CONVERT(Varchar(4), Year)) + ' Varchar(20) null'            
            From [dbo].MyTable
            Order By 1 
            For XML Path('')),1,1,'')+ ')
INSERT INTO ##TestTable
Select *
 From (
        Select A.ID, A.Payments
              ,B.*
         From  [dbo].MyTable a 
         Cross Apply ( values ( Channel + CONVERT(Varchar(4), Year)
                     )) B ([Value])
      ) S
 Pivot (sum([Payments]) For [Value] in 
 (' + Stuff((Select Distinct ','+QuoteName(Channel + CONVERT(Varchar(4), Year))                                                               
                                               From myTable
                                               Order By 1 
                                               For XML Path('')),1,1,'')  + ') ) p'

--SELECT @SQL

Exec(@SQL)

SELECT * FROM ##TestTable

Вы можете найти демонстрационную версию здесь .

0 голосов
/ 25 января 2019

Для этого можно использовать динамический сводный запрос.

-- data

create table testTable
(
    Id int,
    Year int,
    Channel varchar(10),
    Payments int
)

 insert into testTable values (1,2012,'HV',100)
 insert into testTable values (1,2014,'HV',56)
 insert into testTable values (2,2012,'NL',17000)
 insert into testTable values (2,2012,'HV',495)
 insert into testTable values (3,2013,'HV',565)


-- query
DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX);

SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(CONCAT(c.Channel,c.Year))
            FROM testTable c
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')


set @query = 'SELECT Id, ' + @cols + ' from 
            (
                select Id
                    , CONCAT(Channel,Year ) YC
                    , Payments
                from testTable
           ) x
            pivot 
            (
                 max(Payments)
                for YC in (' + @cols + ')
            ) p '

execute(@query)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...