【问题标题】:SQL - spread previous values from one column into multiple new columnsSQL - 将以前的值从一列传播到多个新列
【发布时间】:2019-06-22 15:03:07
【问题描述】:

我有一个 Customer_ID 的 SQL 表,按年份显示付款。第一个(许多)客户如下所示:

 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

我很清楚这是数据的大量重复,因此看起来很奇怪。不过,我还是想做! (正在为预测模型准备数据,其中将使用以前的付款(和其他信息)来预测当年的付款)

我不确定从哪里开始。我一直在研究使用数据透视,但不知道如何让它从客户上一年选择值。

我非常想在 SQL 中执行此操作。如果这不可能,我可以将表复制到 R 中 - 但 SQL 是我的首选。

非常感谢任何帮助。

【问题讨论】:

    标签: sql r sql-server-2012 dplyr pivot


    【解决方案1】:

    如果你有完整的数据,你可以使用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
         . . .;
    

    【讨论】:

    • 非常感谢,“左连接”解决方案对我来说效果很好。如果我在一个查询中运行所有连接,这将需要很长时间,所以我最终运行了 10 个单独的连接,每个新列一个。
    【解决方案2】:

    我想你的朋友会是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
    

    【讨论】:

      猜你喜欢
      • 2020-11-24
      • 1970-01-01
      • 2018-09-26
      • 1970-01-01
      • 1970-01-01
      • 2017-06-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多