如何在 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 分区和任何其他细节应该从这里直接开始。