LAG函数在第一行和重复分区组上的行为

时间:2018-10-02 07:52:37

标签: sql-server sql-server-2012 lag lead

我正在尝试在MSSQL中使用LAG()函数,并且出现了奇怪的行为。 该表如下所示:

    ID  TotalReadings    Month     Device
0    1    4           January         M  
1    1    4           January         D  
2    1    4           January         T  
2    1    4           January         L  
2    1    2           February        M  
2    1    2           February        D  
2    1    2           February        L  
0    1    2           February        T  
1    1    6           March           M  
2    1    6           March           D  
2    1    6           March           L  
2    1    6           March           T  
2    1    6           April           M  
2    1    6           April           D  
2    1    6           April           T  
2    1    6           April           L  

我所做的是:

Select *,
    CASE 
        WHEN 
             ISNULL(LAG(TotalReadings) OVER (PARTITION BY ID ORDER BY Month ), 0) < TotalReadings THEN 'Increase' 
        WHEN
             ISNULL(LAG(TotalReadings) OVER (PARTITION BY ID ORDER BY Month), 0) = TotalReadings THEN 'Neutral'
        WHEN
             ISNULL(LAG(TotalReadings) OVER (PARTITION BY ID ORDER BY Month), 0) > TotalReadings THEN 'Decrease'
    END As Trend 
from table

并得到:

    ID  TotalReadings    Month     Device   Trend
0    1    4           January         M      Increase
1    1    4           January         D      Neutral
2    1    4           January         T      Neutral
2    1    4           January         L      Neutral
2    1    2           February        M      Decrease
2    1    2           February        D      Neutral
2    1    2           February        L      Neutral
0    1    2           February        T      Neutral
1    1    6           March           M      Increase
2    1    6           March           D      Neutral
2    1    6           March           L      Neutral
2    1    6           March           T      Neutral
2    1    6           April           M      Neutral
2    1    6           April           D      Neutral
2    1    6           April           T      Neutral
2    1    6           April           L      Neutral

但是我真正想要的是首先按月分组,并将趋势命名为“开始”,因为没有可与之比较的先前值,而剩余部分应考虑类似的TOtalReadings,每月总计相同,因此趋势不应该只针对新月行开始的第一行,而是所有趋势:

    ID  TotalReadings    Month     Device   Trend
0    1    4           January         M      Start
1    1    4           January         D      Start
2    1    4           January         T      Start
2    1    4           January         L      Start
2    1    2           February        M      Decrease
2    1    2           February        D      Decrease
2    1    2           February        L      Decrease
0    1    2           February        T      Decrease
1    1    6           March           M      Increase
2    1    6           March           D      Increase
2    1    6           March           L      Increase
2    1    6           March           T      Increase
2    1    6           April           M      Neutral
2    1    6           April           D      Neutral
2    1    6           April           T      Neutral
2    1    6           April           L      Neutral

有任何线索吗?

2 个答案:

答案 0 :(得分:0)

您在这里:

    create table #t
    (id int, totalreadings int, month int, device char(1))

    insert into #t
    values
    (1,4,1,'M'),
    (1,4,1,'D'),
    (1,4,1,'T'),
    (1,4,1,'L'),
    (1,2,2,'M'),
    (1,2,2,'D'),
    (1,2,2,'L'),
    (1,2,2,'T'),
    (1,6,3,'M'),
    (1,6,3,'D'),
    (1,6,3,'L'),
    (1,6,3,'T'),
    (1,6,4,'M'),
    (1,6,4,'D'),
    (1,6,4,'L'),
    (1,6,4,'T')


    Select *,
        CASE 
            WHEN 
                 LAG(TotalReadings) OVER (PARTITION BY ID,device ORDER BY Month ) < TotalReadings THEN 'Increase' 
            WHEN
                 LAG(TotalReadings) OVER (PARTITION BY ID,device ORDER BY Month) = TotalReadings THEN 'Neutral'
            WHEN
                 LAG(TotalReadings) OVER (PARTITION BY ID,device ORDER BY Month) > TotalReadings THEN 'Decrease'
            ELSE 'Start'
        END As Trend 
    from #t
    order by month

id  totalreadings   month   device  Trend
1   4   1   D   Start
1   4   1   L   Start
1   4   1   M   Start
1   4   1   T   Start
1   2   2   T   Decrease
1   2   2   M   Decrease
1   2   2   L   Decrease
1   2   2   D   Decrease
1   6   3   D   Increase
1   6   3   L   Increase
1   6   3   M   Increase
1   6   3   T   Increase
1   6   4   T   Neutral
1   6   4   M   Neutral
1   6   4   L   Neutral
1   6   4   D   Neutral

答案 1 :(得分:0)

如果添加identity列,则可以使用此代码

create table #order ( i int identity(1,1),  ID  int, TotalReadings    int, Month     varchar(20), Device varchar(1))
insert #order values
(  1  ,  4           ,'January'         ,'M' ) 
,(  1  ,  4           ,'January'         ,'D' ) 
,(  1  ,  4           ,'January'         ,'T' ) 
,(  1  ,  4           ,'January'         ,'L' ) 
,(  1  ,  2           ,'February'       ,'M'  )
,(  1  ,  2           ,'February'       ,'D'  )
,(  1  ,  2           ,'February'       ,'L'  )
,(  1  ,  2           ,'February'       ,'T'  )
,(  1  ,  6           ,'March'           ,'M' ) 
,(  1  ,  6           ,'March'           ,'D' ) 
,(  1  ,  6           ,'March'           ,'L' ) 
,(  1  ,  6           ,'March'           ,'T' ) 
,(  1  ,  6           ,'April'           ,'M' ) 
,(  1  ,  6           ,'April'           ,'D' ) 
,(  1  ,  6           ,'April'           ,'T' ) 
,(  1  ,  6           ,'April'           ,'L' )

Select *
    ,CASE 
        WHEN 
             lag(TotalReadings, 4) OVER (PARTITION BY ID ORDER BY i,id, Month)  < TotalReadings THEN 'Increase' 
        WHEN                                                                   
             lag(TotalReadings, 4) OVER (PARTITION BY ID ORDER BY i,id, Month)  = TotalReadings THEN 'Neutral'
        WHEN                                                                   
             lag(TotalReadings, 4) OVER (PARTITION BY ID ORDER BY i,id, Month)  > TotalReadings THEN 'Decrease'
        WHEN                                                                   
             lag(TotalReadings, 4) OVER (PARTITION BY ID ORDER BY i,id, Month)  is null THEN 'start'
    END As Trend 
from #order
order by i

编辑1:无需身份列

Select *
    ,CASE 
        WHEN 
             lag(TotalReadings, 4) OVER (PARTITION BY ID ORDER BY id, MONTH(MONTH + ' 1 2014') )  < TotalReadings THEN 'Increase' 
        WHEN                                                         
             lag(TotalReadings, 4) OVER (PARTITION BY ID ORDER BY id, MONTH(Month + ' 1 2014') )  = TotalReadings THEN 'Neutral'
        WHEN                                                         
             lag(TotalReadings, 4) OVER (PARTITION BY ID ORDER BY id, MONTH(Month + ' 1 2014') )  > TotalReadings THEN 'Decrease'
        WHEN                                                          
             lag(TotalReadings, 4) OVER (PARTITION BY ID ORDER BY id, MONTH(Month + ' 1 2014') )  is null THEN 'start'
    END As Trend 
from #order
order by MONTH(Month + ' 1 2014')