如何在 Redshift 中获取过去 x 天前所有行的最小值
How to get the minimal value for all rows before x days in the past in Redshift
假设我有以下 table tbl
,所有行都具有相同的 id
以简化事情
timestamp amount
------------------
01-01-2021 10
02-01-2021 15
03-01-2021 11
02-02-2021 20
01-04-2021 9
我想要一个新列 prev_min
过去 至少 x 天 所有订单的最小金额。这将导致:
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
我的做法是这样的
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
我知道 CASE WHEN ...
是错误的。而且我也知道 30 PRECEDING
是从当前行之前的 30 行开始的,因此也是错误的。我不想要例如过去 30 行,而不是过去 30 天。但是我不能使用 RANGE
。
那么有没有办法不使用 RANGE
来做到这一点?
谢谢!
您将需要为每个日期创建行,以便您可以按需要使用 window 函数的 frame 子句。我使用递归 CTE 生成了 2021 年的所有日期,但您可以根据需要扩展它。
测试用例:
设置:
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);
查询:
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
;
添加您的 id 分区和任何其他细节应该从这里直接开始。
假设我有以下 table tbl
,所有行都具有相同的 id
以简化事情
timestamp amount
------------------
01-01-2021 10
02-01-2021 15
03-01-2021 11
02-02-2021 20
01-04-2021 9
我想要一个新列 prev_min
过去 至少 x 天 所有订单的最小金额。这将导致:
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
我的做法是这样的
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
我知道 CASE WHEN ...
是错误的。而且我也知道 30 PRECEDING
是从当前行之前的 30 行开始的,因此也是错误的。我不想要例如过去 30 行,而不是过去 30 天。但是我不能使用 RANGE
。
那么有没有办法不使用 RANGE
来做到这一点?
谢谢!
您将需要为每个日期创建行,以便您可以按需要使用 window 函数的 frame 子句。我使用递归 CTE 生成了 2021 年的所有日期,但您可以根据需要扩展它。
测试用例:
设置:
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);
查询:
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
;
添加您的 id 分区和任何其他细节应该从这里直接开始。