I have the first three fields of the following table. I want to compute the number of consecutive days an amount was higher than 0 ("days" field).
key | date | amount | days |
---|---|---|---|
1 | 2023-01-23 | 0 | 0 |
1 | 2023-01-22 | 10 | 2 |
1 | 2023-01-21 | 20 | 1 |
1 | 2023-01-20 | 0 | 0 |
1 | 2023-01-19 | 0 | 0 |
1 | 2023-01-18 | 0 | 0 |
1 | 2023-01-17 | 3 | 1 |
1 | 2023-01-16 | 0 | 0 |
I have tried with some windows function using this link. Did not add and reset to 1 if the previous amount is 0.
My code:
case when f.amount > 0
then SUM ( DATE_PART('day',
date::text::timestamp - previou_bus_date::text::timestamp )
) OVER (partition by f.key
ORDER BY f.date
ROWS BETWEEN 1 PRECEDING AND CURRENT ROW )
else 0
end as days
2
Answers
This problem falls into the gaps-and-islands kind of problem, as long as you need to compute consecutive values of non-null amounts.
You can reliably solve this problem in 3 steps:
SUM
) on flags generated at step 1, to create your partitioning, which to observe the number of consecutive values onROW_NUMBER
) to rank your non-null consecutive amounts in each partition generated at step 2Check the demo here.
Note: This is not the most performant solution, although I’m leaving it for reference to the next part (missing consecutive dates). @Ahmed’s answer is more likely to work better in this case.
If your data should ever have holes in dates (some missing records, making the consecutiveness of amounts no-more valid), you should add a further condition in Step 1, where you create the flag for changing partition.
The partition should change:
Check the demo here.
Another option, you could use the difference between two
row_number
s approach as the following:See demo