Reputation: 772
Let's say that I have the following table tbl
with all rows having the same id
to simplify things
timestamp amount
------------------
01-01-2021 10
02-01-2021 15
03-01-2021 11
02-02-2021 20
01-04-2021 9
I want as a new column prev_min
the minimal amount for all orders which are at least x days in the past. This would result in:
timestamp amount prev_min
--------------------------------
01-01-2021 10 NULL
02-01-2021 15 NULL
03-01-2021 11 NULL
02-02-2021 20 10 -- since 11 & 15 are not > 30 days in the past
01-04-2021 9 11 -- since 11 is > 30 days in the past
My approach is something like that
SELECT
MIN(CASE WHEN timestamp < timestamp - INTERVAL '30 DAYS'
THEN amount
ELSE 0 END)
OVER (
PARTITION BY id
ORDER BY timestamp ASC
ROWS BETWEEN UNBOUNDED PRECEDING AND 30 PRECEDING
) AS prev_min
FROM tbl
I know that the CASE WHEN ...
is wrong. And I also know that the 30 PRECEDING
is starting from 30 rows before the current row and thus is also wrong. And I don't want e.g. 30 rows in the past but rather 30 days in the past. I can't use RANGE
however.
So is there a way to do that without using RANGE
?
Thanks!
Upvotes: 0
Views: 730
Reputation: 11032
You're going to need to have rows for every date so you can use the frame clause of the window function the way you want. I used a recursive CTE to generate all the dates of 2021 but you can expand this as you need.
Test case:
Setup:
create table t (dt date, amount int);
insert into t values
('01-01-2021', 10),
('01-02-2021', 15),
('01-03-2021', 11),
('02-02-2021', 8),
('04-01-2021', 9);
Query:
with recursive dates(d) as
( select '2021-01-01'::date as d
union all
select (d + 1)::date as d
from dates d
where d.d <= '2021-12-31'::date
)
select dt, amount, prev_min
from (
select dt, sum(amount) as amount, max(orig) as orig,
min(sum(amount)) over (
ORDER BY dt ASC
ROWS BETWEEN UNBOUNDED PRECEDING AND 30 PRECEDING) as prev_min
from (
select dt, amount, 1 as orig from t
union all
select d as dt, null as amount, 0 as orig from dates
) as a
group by dt
) b
where orig = 1
order by dt
;
Adding in your id partition and any other specifics should be straight forward from here.
Upvotes: 1