Redshift中按UserID分组填充最后非空值及初始NULL替换方案
在Redshift中按UserID填充最后一个非空值
针对你提出的需求——按UserID向前填充最后一个非空的Value,且新用户初始为NULL时替换为0,我们可以利用Redshift支持的窗口函数和条件函数来实现,下面是具体的解决方案:
需求回顾
你的原始数据集(整理后):
| Date | UserID | Value |
|---|---|---|
| 4-18-2018 | abc | 1 |
| 4-19-2018 | abc | NULL |
| 4-20-2018 | abc | NULL |
| 4-21-2018 | abc | 8 |
| 4-19-2018 | def | 9 |
| 4-20-2018 | def | 10 |
| 4-21-2018 | def | NULL |
| 4-22-2018 | tey | NULL |
| 4-23-2018 | tey | 2 |
期望结果:所有NULL的Value被同用户上一个非空值填充,tey用户第一条的NULL替换为0。
解决方案SQL
WITH ranked_data AS ( SELECT Date, UserID, Value, -- 按用户分组、日期排序,获取到当前行为止最后一个非空的Value(实现向前填充) LAST_VALUE(Value IGNORE NULLS) OVER ( PARTITION BY UserID ORDER BY Date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) AS filled_value FROM your_table_name ) SELECT Date, UserID, -- 处理用户初始值为NULL的情况,替换成0 COALESCE(filled_value, 0) AS Value FROM ranked_data ORDER BY UserID, Date;
代码细节解释
LAST_VALUE(Value IGNORE NULLS):这是实现填充的核心,IGNORE NULLS会自动跳过NULL值,只追踪非空的Value;PARTITION BY UserID确保我们只在同一个用户的记录范围内计算;ORDER BY Date保证按时间顺序取前一个有效Value;ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW限定计算范围是从当前用户的第一条记录到当前行,避免提前获取后面的数值。COALESCE(filled_value, 0):如果某个用户的第一条记录就是NULL,窗口函数返回的filled_value也会是NULL,这时候用COALESCE把它替换成0,满足你的特殊需求。- CTE
ranked_data:先通过子查询完成窗口函数的计算,再在外部处理初始NULL的情况,让逻辑更清晰易读。
最终验证结果
运行上述SQL后,你会得到完全符合期望的结果:
| Date | UserID | Value |
|---|---|---|
| 4-18-2018 | abc | 1 |
| 4-19-2018 | abc | 1 |
| 4-20-2018 | abc | 1 |
| 4-21-2018 | abc | 8 |
| 4-19-2018 | def | 9 |
| 4-20-2018 | def | 10 |
| 4-21-2018 | def | 10 |
| 4-22-2018 | tey | 0 |
| 4-23-2018 | tey | 2 |
内容的提问来源于stack exchange,提问作者Nick Knauer
相关产品推荐
相关产品推荐

