基于非零数值为后续月份分配状态的SQL查询需求
基于最后一个非零值的月度状态分配SQL查询
需求
从给定的月度数据中,依据最后一个非零数值的时间为后续月份分配对应状态:
- 非零数值所在月份标记为
'Active' - 非零数值后的前3个月标记为
'Newly Inactive' - 非零数值后的第4至第6个月标记为
'Inactive' - 非零数值后的第7个月及以后标记为
'Frozen'
输入数据
| 月份 | 数值 |
|---|---|
| 01-11-2019 | 10 |
| 01-12-2019 | 0 |
| 01-01-2020 | 0 |
| 01-02-2020 | 0 |
| 01-03-2020 | 0 |
| 01-04-2020 | 0 |
| 01-05-2020 | 0 |
| 01-06-2020 | 0 |
| 01-07-2020 | 0 |
| 01-08-2020 | 0 |
| 01-09-2020 | 0 |
| 01-10-2020 | 0 |
| 01-11-2020 | 0 |
| 01-12-2020 | 0 |
预期输出
| 月份 | 数值 | 状态 |
|---|---|---|
| 01-11-2019 | 10 | Active |
| 01-12-2019 | 0 | Newly Inactive |
| 01-01-2020 | 0 | Newly Inactive |
| 01-02-2020 | 0 | Newly Inactive |
| 01-03-2020 | 0 | Inactive |
| 01-04-2020 | 0 | Inactive |
| 01-05-2020 | 0 | Inactive |
| 01-06-2020 | 0 | Inactive |
| 01-07-2020 | 0 | Inactive |
| 01-08-2020 | 0 | Inactive |
| 01-09-2020 | 0 | Frozen |
| 01-10-2020 | 0 | Frozen |
| 01-11-2020 | 0 | Frozen |
| 01-12-2020 | 0 | Frozen |
初始代码问题分析
提供的初始查询存在几个关键问题:
- 使用
LAG(month)仅获取前一行的月份,无法定位到最后一个非零值的月份 - 列名错误:用了
total_amount但输入数据的数值列是value - 状态名称不匹配:写了
'Freshly Inactive',需求是'Newly Inactive' - 时间范围判断错误:需求中第4-6个月为
Inactive,第7个月及以后为Frozen,但代码中写的是4-12个月为Inactive,大于12个月才是Frozen
修正后的SQL查询
WITH stg_status AS ( SELECT month, value, -- 获取全局最后一个非零数值的月份 MAX(CASE WHEN value > 0 THEN month END) OVER () AS last_active_month, -- 计算当前月份与最后活跃月份的间隔(正数表示当前在活跃月份之后) MONTHS_BETWEEN(month, MAX(CASE WHEN value > 0 THEN month END) OVER ()) AS month_diff FROM my_table ) SELECT month, value, CASE WHEN value > 0 THEN 'Active' WHEN month_diff BETWEEN 1 AND 3 THEN 'Newly Inactive' WHEN month_diff BETWEEN 4 AND 6 THEN 'Inactive' WHEN month_diff >=7 THEN 'Frozen' ELSE NULL -- 理论上不会出现,处理边界情况 END AS status FROM stg_status ORDER BY month;
代码说明
- 通过
MAX(CASE WHEN value>0 THEN month END) OVER ()获取所有数据中最后一个有非零值的月份 - 用
MONTHS_BETWEEN计算当前月份与该活跃月份的间隔 - 根据间隔范围匹配对应的状态规则,确保完全符合需求
内容的提问来源于stack exchange,提问作者Nani2011
相关产品推荐
相关产品推荐

