用于更改列的 Redshift window 函数
Redshift window function for change in column
我有一个红移 table,除此之外还有一个 id
和 plan_type
列,我想要一个 window 函数组子句,其中 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 |
这可以用 window 函数实现吗?
编辑
因为我在数据中有一些垃圾,其中 plan_type
有时可以为 null 并且接受的解决方案不包括第一行(因为我不能有 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
过滤掉源 table 和外部 where 子句中的任何更改或不会包含的第一行数据的错误数据。
如果您正在处理 prev_plan
字段,请注意 created_at 时间戳,因为它当然会给您新值的时间!!!
使用row_number()
window函数
select * from
(select *,row_number()over(partition by user_id,plan_type order by created) rn
) a where a.rn=1
这是一个缺口和孤岛问题。我认为 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;
使用lag()
select * from
(
select user_id, plant_type, lag(plan_type) over (partition by user_id order by created) as changes, created
from tablename
)A where plan_type<>changes and changes is not null
我有一个红移 table,除此之外还有一个 id
和 plan_type
列,我想要一个 window 函数组子句,其中 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 |
这可以用 window 函数实现吗?
编辑
因为我在数据中有一些垃圾,其中 plan_type
有时可以为 null 并且接受的解决方案不包括第一行(因为我不能有 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
过滤掉源 table 和外部 where 子句中的任何更改或不会包含的第一行数据的错误数据。
如果您正在处理 prev_plan
字段,请注意 created_at 时间戳,因为它当然会给您新值的时间!!!
使用row_number()
window函数
select * from
(select *,row_number()over(partition by user_id,plan_type order by created) rn
) a where a.rn=1
这是一个缺口和孤岛问题。我认为 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;
使用lag()
select * from
(
select user_id, plant_type, lag(plan_type) over (partition by user_id order by created) as changes, created
from tablename
)A where plan_type<>changes and changes is not null