Home > Net >  Decremental value with SQL Server LAG function not return the expected value after the 2nd row
Decremental value with SQL Server LAG function not return the expected value after the 2nd row

Time:05-06

I'm trying to return a decremental column in SQL SELECT Statement using LAG function. The result until the 2nd row is the expected, but for 3rd the result is different.

The original dataset:

AvailableId Date Hour Consumed Available
158632 2022-05-03 08 4 50
158632 2022-05-03 09 18 50
158632 2022-05-03 10 28 50

The expected result is more one column with Remaining decremental (Available - Consumed):

AvailableId Date Hour Consumed Available Remaining
158632 2022-05-03 08 4 50 50
158632 2022-05-03 09 18 50 46
158632 2022-05-03 10 28 50 28

I tried with the query:

select 
    AvailableId
    ,Date
    ,Hour
    ,Consumed
    ,Available
    ,case 
            when row_number() over(partition by AvailableId order by Date asc, Hour asc) = 1 then Available
            when row_number() over(partition by AvailableId order by Date asc, Hour asc) = 2 then (Available - lag( Consumed ) over(partition by AvailableId order by Date asc, Hour asc))
            else ((Available- lag( Consumed ) over(partition by AvailableId order by Date asc, Hour asc)) - lag( Consumed ) over(partition by AvailableId order by Date asc, Hour asc))
    end as Remaining
from 
    #temp

But the result was:

AvailableId Date Hour Consumed Available Remaining
158632 2022-05-03 08 4 50 50
158632 2022-05-03 09 18 50 46
158632 2022-05-03 10 28 50 14

After the Second Row the decrement not work (46 - 18), this works fine only the AvailableId have two lines. Someone knows how to return the expected result for 3rd, 4th, until N rows in this case?

The DDL:

create table #temp(
    [AvailableId] int not null
    ,[Date] date not null
    ,[Hour] int not null
    ,[Consumed] int null
    ,[Available] int null
)
go
insert into #temp values
    (158632,'2022-03-05',08, 4, 50),
    (158632,'2022-03-05',09, 18, 50),
    (158632,'2022-03-05',10, 28, 50)
go

CodePudding user response:

I follow the tip of #Larnu and I could return the expected result using cumulative sum:

with cte as(
    select 
        t1.AvailableId
        ,t1.Date
        ,t1.Hour
        ,t1.Consumed
        ,t1.Available
        ,sum(t1.Consumed) over(partition by t1.AvailableId order by t1.Date asc, t1.Hour asc) as CumSum
    from 
        #temp as t1
)
select 
    t2.AvailableId
    ,t2.Date
    ,t2.Hour
    ,t2.Consumed
    ,t2.Available
    ,case
        when lag(t2.CumSum) over(partition by t2.AvailableId order by t2.Date asc, t2.Hour asc) is null then t2.Available
        else t2.Available - lag(t2.CumSum) over(partition by t2.AvailableId order by t2.Date asc, t2.Hour asc)
    end as Consumed
from
    cte as t2

Thank you @Larnu!

  • Related