Search code examples
sql-servert-sqlsql-server-2016

Query to retain latest non-zero value


I'm using SQL Server 2016 and have a table with the following data:

PlaySeq TransMaxValue
1 250
2 500
3 0
4 400
5 0
6 300
7 500
8 0
9 0

I'm trying to construct a query that adds a column TransMaxValueContd to that dataset.
That TransMaxValueContd column should retain the last non-zero value encountered in column TransMaxValue.
Ordering is done by PlaySeq.

My expected result from the query is this:

PlaySeq TransMaxValue TransMaxValueContd
1 250 250
2 500 500
3 0 500
4 400 400
5 0 400
6 300 300
7 500 500
8 0 500
9 0 500

I've been using windowing functions like LAST_VALUE() and LAG(), but can't seem to get the results right.
Maybe I'm overcomplicating it.
Does anyone know how to do this?

ps: I'm just looking for the query. No need to modify the source table.

Edit: Added a SQLFiddle example with a failed attempt, which is:

SELECT a.PlaySeq, 
       a.TransMaxValue,
       IIF(ISNULL(LAG(a.TransMaxValue,1) OVER (ORDER BY a.PlaySeq), a.TransMaxValue) = a.TransMaxValue, a.TransMaxValue, LAG(a.TransMaxValue,1) OVER (ORDER BY a.PlaySeq)) AS TransMaxValueContd
FROM   myTable AS a;

Edit: Thank you for all the answers, which provided new useful insights!
I ended up using this, inspired by the answer from SteveC.

SELECT  a.PlaySeq, 
        a.TransMaxValue,
        (SELECT     TOP 1 x.TransMaxValue 
         FROM       myTable AS x 
         WHERE      x.PlaySeq <= a.PlaySeq 
         AND        x.TransMaxValue != 0 
         ORDER BY   x.PlaySeq DESC) AS TransMaxValueContd
FROM    myTable AS a;

Solution

  • A simple way could use OUTER APPLY and SELECT TOP(1). Something like this

    select m.PlaySeq, m.[TransMaxValue],
           case when m.[TransMaxValue]=0 
                then oa.TransMaxValue 
                else m.TransMaxValue end TransMaxValueContd
    from myTable m
         outer apply (select top(1) mm.[TransMaxValue]
                      from myTable mm
                      where m.PlaySeq>mm.PlaySeq
                            and mm.[TransMaxValue]>0
                      order by mm.PlaySeq desc) oa;
    
    PlaySeq TransMaxValue   TransMaxValueContd
    1       250             250
    2       500             500
    3       0               500
    4       400             400
    5       0               400
    6       300             300
    7       500             500
    8       0               500
    9       0               500