首页 > 解决方案 > 用于更改列的红移窗口函数

问题描述

我有一个红移表,其中包含一个idplan_type列,并且想要一个窗口函数组子句,其中会plan_type发生变化,因此如果这是例如数据:

| user_id | plan_type | created    |
|---------|-----------|------------|
| 1       | A         | 2019-01-01 |
| 1       | A         | 2019-01-02 |
| 1       | B         | 2019-01-05 |
| 2       | A         | 2019-01-01 |
| 2       | A         | 2-10-01-05 |

我想要这样的结果,我得到第一个plan_type“新”日期:

| user_id | plan_type | created    |
|---------|-----------|------------|
| 1       | A         | 2019-01-01 |
| 1       | B         | 2019-01-05 |
| 2       | A         | 2019-01-01 |

这可以通过窗口函数实现吗?

编辑

由于我在数据中有一些垃圾,plan_type有时可能为空,并且接受的解决方案不包括第一行(因为我不能让OR is not null我不得不进行一些修改。希望他能帮助其他人,如果他们有类似的问题。最终查询如下:

SELECT * FROM
(
 SELECT 
    user_id, 
    plan_type, 
    created_at,
    lag(plan_type) OVER (PARTITION by user_id ORDER BY created_at) as prev_plan,
    row_number() OVER (PARTITION by user_id ORDER BY created_at) as rownum 
 FROM tablename
 WHERE plan_type IS NOT NULL
) userHistory 
WHERE
    userHistory.plan_type <> userHistory.prev_plan
    OR userHistory.rownum = 1
ORDER BY created_at;

过滤掉源表中的plan_type IS NOT NULL错误数据,外部 where 子句获取任何更改或第一行数据,否则不会包含在内。

如果你在你的领域工作,还要小心 created_at 时间戳,prev_plan因为它当然会给你新值的时间!!!

标签: sqlamazon-redshiftgaps-and-islands

解决方案


这是一个差距和孤岛问题。我认为lag()是最简单的方法:

select user_id, plan_type, created
from (select t.*,
             lag(plan_type) over (partition by user_id order by created) as prev_plan_type
      from t
     ) t
where prev_plan_type is null or prev_plan_type <> plan_type;

这假设计划类型可以移回另一个值,并且您需要每个值。

如果没有,只需使用聚合:

select user_id, plan_type, min(created)
from t
group by user_id, plan_type;

推荐阅读