This might be a bit elaborate so please bear with me. I’m looking to create a new column free_duration in a table that currently looks like this, when grouped by country and product in ASCENDING order of month-
month country product stock
7/1/10 Wakanda Vibranium 7166
8/1/10 Wakanda Vibranium 6189
9/1/10 Wakanda Vibranium 1987
10/1/10 Wakanda Vibranium 98
11/1/10 Wakanda Vibranium 23
12/1/10 Wakanda Vibranium 1
1/1/11 Wakanda Vibranium 29999
2/1/11 Wakanda Vibranium 2314
3/1/11 Wakanda Vibranium 19
The new column free_duration, for a given row x1, is basically the count of number of months where stock column
values are lesser than or equal to the stock column value in that row x1, until more stock comes up (that is, the stock value increases next).
In the example, for row 1, arranged in ascending order of month, stock in July ’10 is 7166 – free_duration value for July ’10 should therefore be 5 because for 5 consecutive months, the stock column value is lesser than 7166 in row 1, until the next higher value is hit. Same way, for row 6, Dec ’10, stock available is 1, and given the next immediate month the stock is greater than 1, free_duration should be 0.
To summarize, I need to take one value in a column, count down that same column all the less than or equal values, UNTIL the next immediate greater value is reached.
My query almost does it but with one logic flaw- Within each group, it ends up counting all lesser values and not setting the upper cap of limiting the count to until the next higher value is reached.
WITH ranking AS (SELECT month,
country,
product,
stock,
ROW_NUMBER() OVER (PARTITION BY country, product ORDER BY month) AS rn
FROM data_table),
free_duration_cte AS (SELECT r1.month,
r1.country,
r1.product,
r1.stock,
COALESCE((SELECT COUNT(*)
FROM ranking r2
WHERE r1.country = r2.country
AND r1.product = r2.product
AND r2.rn > r1.rn
AND r2.stock <=
r1.stock), 0) AS free_duration
FROM ranking r1)
SELECT *
FROM free_duration_cte
ORDER BY country, product, month;
I’ve tried multiple other things to merely set the upper cap, and the simplest would involve FIRST_VALUE() which is not accepted in Redshift. Any help to make the change needed will really be appreciated.
2
Answers
Is this what you are looking for?
One of the options to do it is to:
See the fiddle here.