Given the following tables:
users:
name |
---|
alice |
bob |
balances:
id | user_name | date | balance |
---|---|---|---|
1 | alice | 2022-01-01 | 100 |
2 | alice | 2022-01-03 | 200 |
3 | alice | 2022-01-04 | 300 |
4 | bob | 2022-01-01 | 400 |
5 | bob | 2022-01-02 | 500 |
6 | bob | 2022-01-05 | 600 |
I would like to get a full list of all days from the first available to the last for all users, replacing NULL balances with the last available balance for that user.
This is what I have so far:
select u.name, s.day, b.balance
from users u
cross join (select generate_series(min(day)::date, max(day)::date, interval '1 day')::date as day from balances) s
left join balances b on b.user_name = u.name and s.day = b.day
order by u.name, s.day
;
I have tried LAG()
and some other examples found here but none of them seem to get the right last balance for the user.
2
Answers
Based on How do I efficiently select the previous non-null value?, I ended up getting successful results with the following query:
DB Fiddle
We group every
balance
with thenulls
that come after it by usingcount() over()
and then we usemax() over()
to give the entire group the same value.Fiddle