sqlsql-servergaps-and-islands

Windowing Function To Keep Track Of "Latest Seen" Row


I have the following test data:

Id Special
1 0
2 0
3 1
4 0
5 0
6 0
7 1
8 0
9 0

And I want to compute this:

Id Special LastSeenSpecial
1 0 NULL
2 0 NULL
3 1 3
4 0 3
5 0 3
6 0 3
7 1 7
8 0 7
9 0 7

from it.

I have thought about a query snippet that does something like MIN(Id) OVER (PARTITION BY Special ORDER BY Id), but the partitioning comes out wrong and the default value for rows with Id 1 and 2 come out as 1, instead of the required NULL. How can I achieve this? I figure I need to use windowing in some way, but there's no need to use ROW_NUMBER() since Id is already effectively the row number.

What do?


Solution

  • One way is to use a windowed MAX with conditional aggregation Fiddle

    SELECT Id, 
           Special, 
           MAX(CASE WHEN Special = 1 THEN Id END) OVER (ORDER BY Id ROWS UNBOUNDED PRECEDING)
    FROM YourTable 
    ORDER BY Id
    

    You could also use

     LAST_VALUE (CASE WHEN Special = 1 THEN Id END) IGNORE NULLS OVER (ORDER BY Id ROWS UNBOUNDED PRECEDING )
    

    If you are on a version of SQL Server supporting IGNORE NULLS here.