SQL - разбить предыдущие значения из одного столбца в несколько новых столбцов - PullRequest
0 голосов
/ 29 января 2019

У меня есть таблица SQL Customer_ID, показывающая платежи по годам.Первый (из многих) клиент выглядит так:

 ID    Payment    Year
112          0    2004
112          0    2005
112          0    2006
112       9592    2007
112      12332    2008
112       9234    2011
112       5400    2012
112       7392    2014
112       8321    2015

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

 ID    Payment    Year   T-1  T-2  T-3  T-4  T-5  T-6  T-7  T-8  T-9 T-10   
112          0    2004  NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
112          0    2005     0 NULL NULL NULL NULL NULL NULL NULL NULL NULL
112          0    2006     0    0 NULL NULL NULL NULL NULL NULL NULL NULL
112        952    2007     0    0    0 NULL NULL NULL NULL NULL NULL NULL
112       1232    2008   952    0    0    0 NULL NULL NULL NULL NULL NULL
112        924    2011  NULL NULL 1232  952    0    0    0 NULL NULL NULL 
112        500    2012   924 NULL NULL 1232  952    0    0    0 NULL NULL 
112        392    2014  NULL  500  924 NULL NULL 1232  952    0    0    0
112        821    2015   392 NULL  500  924 NULL NULL 1232  952    0    0

Я хорошо знаю, что это большое дублирование данных, и поэтому кажется странным заняться.Тем не менее, я все еще хотел бы сделать это!(данные готовятся для прогнозирующей модели, в которой предыдущие платежи (и другая информация) будут использоваться для прогнозирования платежей текущего года)

Я не совсем уверен, с чего начать.Я рассматривал использование pivot, но не могу понять, как заставить его выбирать значения из предыдущего года клиента.

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

Любая помощь очень ценится.

Ответы [ 2 ]

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

Я думаю, ваш друг будет LAG

Вот реализация:

Declare @t table (
    ID int,
    Payment int,
    Yr int
)
Insert Into @t Values(112,0,2004)
Insert Into @t Values(112,0,2005)
Insert Into @t Values(112,0,2006)
Insert Into @t Values(112,9592,2007)
Insert Into @t Values(112,12332,2008)
Insert Into @t Values(112,9234,2011)
Insert Into @t Values(112,5400,2012)
Insert Into @t Values(112,7392,2014)
Insert Into @t Values(112,8321,2015)

Insert Into @t Values(113,0,2009)
Insert Into @t Values(113,9234,2011)
Insert Into @t Values(113,5400,2013)
Insert Into @t Values(113,8321,2015)


;with E1(n) as (Select 1 Union All Select 1 Union All Select 1 Union All Select 1 Union All Select 1 Union All Select 1 Union All Select 1 Union All Select 1 Union All Select 1 Union All Select 1)
,E2(n) as (Select 1 From E1 a, E1 b)
,E4(n) as (Select 1 From E2 a, E2 b)
,E5(n) as (Select row_number() over(order by isnull(null,1)) From E4 a, E1 b)
,IDYears as (
    Select z.ID, Yr = y.n
    From (
        Select 
            Id, 
            MinYear = min(Yr),
            MaxYear = max(Yr)
        From @t a
        Group By Id
        ) z
    Inner Join E5 y On y.n between z.MinYear and z.MaxYear
)

Select 
    *,
    [t-1] = Lag(B.Payment, 1) Over(Partition By a.ID Order By a.Yr),
    [t-2] = Lag(B.Payment, 2) Over(Partition By a.ID Order By a.Yr),
    [t-3] = Lag(B.Payment, 3) Over(Partition By a.ID Order By a.Yr),
    [t-4] = Lag(B.Payment, 4) Over(Partition By a.ID Order By a.Yr),
    [t-5] = Lag(B.Payment, 5) Over(Partition By a.ID Order By a.Yr),
    [t-6] = Lag(B.Payment, 6) Over(Partition By a.ID Order By a.Yr),
    [t-7] = Lag(B.Payment, 7) Over(Partition By a.ID Order By a.Yr),
    [t-8] = Lag(B.Payment, 8) Over(Partition By a.ID Order By a.Yr),
    [t-9] = Lag(B.Payment, 9) Over(Partition By a.ID Order By a.Yr),
    [t-10] = Lag(B.Payment, 10) Over(Partition By a.ID Order By a.Yr)
From IDYears a
Left Join @t b On a.ID = b.ID and a.Yr = b.Yr
Order By A.ID
0 голосов
/ 29 января 2019

Вы можете использовать lag(), если у вас были полные данные:

select t.*,
       lag(payment, 1) over (partition by id order by year) as t_1,
       lag(payment, 2) over (partition by id order by year) as t_2,
       . . .
from t;

Однако для вашей ситуации с отсутствующими промежуточными годами left join может быть проще:

select t.*,
       t1.payment as t_1,
       t2.payment as t_2,
       . . .
from t left join
     t t1
     on t1.id = t.id and
        t1.year = t.year - 1 left join
     t t2
     on t1.id = t.id and
        t1.year = t.year - 2 left join
     . . .;
...