在红移中以滚动 12 个月为基础迭代生成的系列

Iterating through generated series on a rolling 12-months-basis in redshift

DB-Fiddle

CREATE TABLE customers (
    id SERIAL PRIMARY KEY,
    order_date DATE,
    customer VARCHAR(255)
);

INSERT INTO customers
(order_date, customer)
VALUES 
('2020-03-10', 'user_01'),
('2020-03-18', 'user_02'),
('2020-03-26', 'user_03'),

('2020-04-12', 'user_04'),
('2020-04-19', 'user_05'),
('2020-04-23', 'user_06'),


('2021-03-09', 'user_01'),
('2021-03-17', 'user_07'),

('2021-04-03', 'user_02'),
('2021-04-18', 'user_05'),
('2021-04-20', 'user_08');

预期结果:

churn_date    |   customer   |
--------------|--------------|----
2021-03-18    |   user_02    |
2021-03-26    |   user_03    |
--------------|--------------|-----
2021-04-12    |   user_04    |
2021-04-23    |   user_06    |

我想迭代 12 个月滚动基础检查每个客户个月 如果客户的最后一个订单是在 12 个月前下的。

例如:
user_02 应该出现在 March 的结果中,但不应出现在 April 的结果中。
March 认为上次订单发生在 12 个月前的 2020-03-18
April 看来,最后的订单发生在 2021-04-03


postgresSQL中,我可以通过:

的解决方案实现这一点
SELECT 
gs.month AS month, 
c.customer AS customer, 
MAX(c.order_date + interval '12 month')::date as churn_date
FROM customers c 

    CROSS JOIN
    GENERATE_SERIES('2021-03-01'::date, '2021-04-01'::date, interval '1 month') AS gs(month)

WHERE c.order_date < gs.month + interval '1 month'
GROUP BY 1,2
HAVING DATE_TRUNC('month', MAX(c.order_date)) = DATE_TRUNC('month', gs.month) - interval '12 month';

但是,在 amazon-redshift 中,我得到一个错误,指出 GENERATE_SERIES 函数不存在。
我必须如何修改查询才能使其在 amazon-redshift 中也能正常工作?

在 Redshift 中,您需要显式定义 table。一种方法是内联:

SELECT gs.month AS month, c.customer AS customer, 
       MAX(c.order_date + interval '12 month')::date as churn_date
FROM customers c CROSS JOIN
     (SELECT '2021-03-01'::date as month UNION ALL
      SELECT '2021-04-01'::date as month UNION ALL
      . . .
     ) gs
WHERE c.order_date < gs.month + interval '1 month'
GROUP BY 1, 2
HAVING DATE_TRUNC('month', MAX(c.order_date)) = DATE_TRUNC('month', gs.month) - interval '12 month';

您可以玩其他把戏——例如,如果您有日历 table 或数字 table 或任何具有 12 行的 table:

FROM customers c CROSS JOIN
     (SELECT (date + (ROW_NUMBER() OVER () - 1) * INTERVAL '1 MONTH') as month 
      FROM (SELECT '2012-03-01'::date as date
            FROM <any table with 12 rows>
            LIMIT 12
           ) gs
      LIMIT 12
     ) gs