Search code examples
sqlpostgresqlwindow-functions

Postgresql selecting first item of last group


I have this data:

ID | Amount
1 | 0
2 | 0
3 | 0
4 | 0 ---> NULL

ID | Amount
1 | -1 ---> this row
2 | 0
3 | 0
4 | 0
5 | 0

ID | Amount
1 | 0
2 | 0
3 | -1 ---> this row
4 | 0
5 | 0
6 | 0
7 | 0

ID | Amount
1 | 0
2 | -1
3 | -1
4 | 0
5 | 0
6 | -1 ---> this row
7 | 0
8 | 0

ID | Amount
1 | 0
2 | -1
3 | 0
4 | 0
5 | 0
6 | -1 ---> this row
7 | -1
8 | 0

my logic is start at the end, and move up until we hit the first -1. However, I am unable to arrive at an SQL for this. Any help is appreciated!


Solution

  • Assuming you have -1s, you can group them by counting the 0s that follow. These can then be enumerated using dense_rank():

    select id, rnk
    from (select t.*, dense_rank() over (partition by grp) as rnk
          from (select t.*,
                       count(*) filter (where amount = 0) over (order by id desc) as grp
                from t
               ) t
         ) t
    where amount = -1 and rnk = 1
    order by id
    fetch first 1 row only;
    

    To handle your first case, you can union in a query like this:

    select id, rnk
    from t
    where not exists (select 1 from t where amount = -1)
    order by id
    fetch first 1 row only