Finding LAST_VALUE With RunningTotals

  • Hello comunity,

    I need to make a query that can retrieve only the last record but with LAST_VALUE(epcpond) as "LastPCM" and also create a RunningTotals for quantities.

    My problem is LAST_VALUE(epcpond) as "LastPCM" are correct but the value of Runningtotals are not!

    This is a simple script to test:

     DROP TABLE #temp
    CREATE TABLE #temp (ref VARCHAR(18), cmdesc VARCHAR(25), adoc VARCHAR(10), cm INT, datalc DATE, qtt NUMERIC(18,4), epcpond NUMERIC(18,6))
    GO

    INSERT INTO #temp ( ref, cmdesc,adoc,cm,datalc,qtt, epcpond)

    SELECT 'ORT A4','S01 Stock inicial', '1', 49, '2014-06-30', 3.000, 27.057044
    UNION
    SELECT 'ORT A4','S03 Transf. Entrada','1549',48, '2014-08-06', 1.000, 27.057044
    UNION
    SELECT 'ORT A4','C11-Fatura Simplific', '193',72, '2014-08-06', 1.000, 27.057044
    UNION
    SELECT 'ORT A4','S03 Transf. Saida', '1549',98, '2014-08-06', 1.000, 27.057044
    UNION
    SELECT 'ORT A4','S03 Transf. Entrada', '1799',48, '2014-08-12', 1.000, 27.057044
    UNION
    SELECT 'ORT A4','C11-Fatura Simplific', '230',72, '2014-08-12', 1.000, 27.057044
    UNION
    SELECT 'ORT A4','S03 Transf. Saida', '1799',98, '2014-08-12', 1.000, 27.057044


    SELECT main.*
    FROM
    (SELECT ref ,cmdesc, adoc,cm,datalc, qtt
    ,sum(case when (cm < 50 OR cm = 60) then ABS(qtt) else -qtt end) over (ORDER BY datalc,cm ASC) AS [RunningTotal]
    ,Row_Number() OVER (ORDER BY datalc, cm DESC) AS RowNum
    , LAST_VALUE(epcpond) OVER(ORDER BY datalc,cm DESC ) [LastPCM]
    FROM #temp a
    WHERE a.ref = 'ORT A4'
    AND a.datalc = '20140812'

    )main
    WHERE main.RowNum = 1

    the value for "LASTPCM" are 27.057044 and is correct , but the runningTotals of quantities are wrong because they return : -1.0000 and the correct value are : 1.0000

     

    Someone could help me with this  ?

    Many thanks,

    Luis

  • It would appear that you have different ORDER BY clauses for your RunningTotal vs RowNum and LastPCM fields.  This will impact the outcome.

  • FYI, in your RunningTotal, you want to frame the query by including a Rows clause

    ORDER BY a.datalc, a.cm ASC 
    ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
  • Hi DesNorton,

     

    Thanks for your reply, also i changed my query following your Advise :

     SELECT main.*
    FROM
    (SELECT ref ,cmdesc, adoc,cm,datalc, qtt
    ,sum(case when (cm < 50 OR cm = 60) then ABS(qtt) else -qtt end) over (ORDER BY datalc,cm ASC) AS [RunningTotal]
    ,Row_Number() OVER (ORDER BY datalc, cm ASC) AS RowNum
    , LAST_VALUE(epcpond) OVER( ORDER BY datalc,cm rows between unbounded preceding and current row) [LastPCM]
    FROM #temp a
    WHERE a.ref = 'ORT A4'
    AND a.datalc = '20140812'
    )main
    WHERE main.RowNum = 1

    but the result of RunningTotal is still incorrect  : -1.0000 and not  1.0000

    Thanks,

    Luis

  • The value for running total looks correct to me. You're only returning the value of the first row, which means that the value of "Running Total" is actually the SUM of a single row. That row has a value of 98 for cm which is not <50 and not 60, which means that -qtt is returned. As qtt has a value of 1 then -1 is returned. Why is -1 therefore "wrong"?

    Thom~

    Excuse my typos and sometimes awful grammar. My fingers work faster than my brain does.
    Larnu.uk

  • Seemed to double post

    • This reply was modified 1 year, 8 months ago by  Ken McKelvey.
  • ,ROW_NUMBER() OVER (ORDER BY datalc, cm desc) AS RowNum

    Using the above on 20140812 the first cm (RowNum = 1) will be 98 so your rules make the running total -1.  You may want:

    ,ROW_NUMBER() OVER (ORDER BY datalc, cm) AS RowNum

    which will make the first cm 48 and the running total 1.

    • This reply was modified 1 year, 8 months ago by  Ken McKelvey.
  • If I run your code against your sample data, i get RuningTotal = 1.0000

  • Hello again,

    I changed my query like this but the result of RunnigTotal are wrog:

    SELECT main.*
    FROM (SELECT ref
    ,datalc,cmdesc, adoc
    ,sum(case when (cm < 50 OR sl.cm = 60) then ABS(qtt) else -qtt end) over (ORDER BY datalc,cm ASC) AS [RunningTotal]
    ,Row_Number() OVER (ORDER BY datalc, cm ) AS RowNum
    --, LAST_VALUE(epcpond) OVER(ORDER BY datalc,cm ASC ) [LastPCM]
    , LAST_VALUE(epcpond) OVER(
    ORDER BY datalc,cm ASC rows between unbounded preceding and current row) [LastPCM]
    FROM sl
    WHERE sl.ref = 'ORT A4 '
    AND sl.datalc = '20220729'
    ) main
    WHERE main.rownum = 1

    Values returns :
    refdatalc cmdesc adocRunningTotalRowNumLastPCM
    ORT A4 2022-07-29 C11-Fatura Simplific1101 -1.000 127.914000 (BAD RunningTotal)

    The result is wrong, this is the calculation:

    a) SELECT 'ORT A4','S01 Stock inicial',      '1', 49,  '2014-06-30', 3.000,  27.057044
    UNION
    b) SELECT 'ORT A4','S03 Transf. Entrada','1549',48, '2014-08-06', 1.000, 27.057044
    UNION
    c) SELECT 'ORT A4','C11-Fatura Simplific', '193',72, '2014-08-06', 1.000, 27.057044
    UNION
    d) SELECT 'ORT A4','S03 Transf. Saida', '1549',98, '2014-08-06', 1.000, 27.057044
    UNION
    e) SELECT 'ORT A4','S03 Transf. Entrada', '1799',48, '2014-08-12', 1.000, 27.057044
    UNION
    f) SELECT 'ORT A4','C11-Fatura Simplific', '230',72, '2014-08-12', 1.000, 27.057044
    UNION
    g) SELECT 'ORT A4','S03 Transf. Saida', '1799',98, '2014-08-12', 1.000, 27.057044

    Formula:
    a =3, b= 1, c=-1, d= -1, e= 1, f= -1, g= -1 THEN
    3 + 1 -1 -1 +1 -1 -1 = 1.0000 (Correct Value for RunningTotal)

    Best regards,

    Luis

  • luissantos wrote:

    Hello again,

    I changed my query like this but the result of RunnigTotal are wrog

    It seems like you don't want a running total here, just a windowed SUM. Remove the ORDER BY from your "running total" and then rename the expression to something else, like Total.

    Thom~

    Excuse my typos and sometimes awful grammar. My fingers work faster than my brain does.
    Larnu.uk

  • Hi Tom,

    I rewrite my query like that, but i have the same problem. Maybe i´am missing something !

     SELECT main.*
    FROM
    (SELECT ref ,cmdesc, adoc,cm,datalc, qtt
    ,sum(case when (cm < 50 OR cm = 60) then ABS(qtt) else -qtt end) over () AS [Total]
    ,Row_Number() OVER (ORDER BY datalc, cm ASC) AS RowNum
    , LAST_VALUE(epcpond) OVER(ORDER BY datalc,cm ASC ) [LastPCM]
    FROM #temp a
    WHERE a.ref = 'ORT A4'
    AND a.datalc = '20140812'

    )main
    WHERE main.RowNum = 1

    Result:
    refcmdesc adoccmdatalc qtt TotalRowNumLastPCM
    ORT A4S03 Transf. Entrada1799482014-08-121.0000-1.0000127.057044

    Best regards,

    Luis

  • Hello again

    I found the solution fo my problem like that:

     SELECT TOP(1) 
    main.*
    from
    ( SELECT ref ,cmdesc, adoc,cm,datalc,
    qtt
    ,sum(case when (cm < 50 OR sl.cm = 60) then ABS(qtt) else -qtt end) OVER (ORDER BY datalc, cm asc) AS [RunningTotal]
    ,Row_Number() OVER (ORDER BY datalc, cm ASC ) AS RowNum
    , LAST_VALUE(epcpond) OVER(ORDER BY datalc, cm asc) [LastPCM]
    FROM sl
    WHERE ref = 'ORT A4'
    AND sl.datalc <= '20180914' ) main
    ORDER BY 8 desc

    This work perfectly returning the RunningTotal and LastPCM on every date i choose on where condition.

     

    Many thanks

    Luis

Viewing 12 posts - 1 through 11 (of 11 total)

You must be logged in to reply to this topic. Login to reply