Teradata环境下计算客户2024年最长连续储蓄月数的技术问询
现有SQL思路分析与修正指导
现有SQL的问题
当前SQL的实现思路完全不符合需求,核心问题包括:
- 把月份列做横向聚合(
MAX(JAN24)等),这种宽表结构无法追踪连续储蓄的月份区间,反而把数据拆碎了。 ROW_NUMBER() OVER(PARTITION BY CUSTOMER_ID ORDER BY MONTH_DATE)生成的CONSEC_MONTHS只是按月份排序的递增序号,不管当月是否储蓄都会+1,完全没结合SAVING_GROWTH里的储蓄标识(值为1才是储蓄),根本体现不了“连续储蓄”的逻辑。- 最后的
QUALIFY子句只是取每个客户的最后一条记录,和最长连续储蓄周期完全无关。
正确实现思路(Teradata适配)
计算最长连续周期的经典方法是差值分组法,结合Teradata的日期函数实现,步骤如下:
- 先将
SAVING_GROWTH的宽表(每月一列)转成窄表结构:每行对应一个客户+一个月份+是否储蓄的标识。 - 过滤出2024年中客户有储蓄(标识=1)的记录,只保留有效储蓄月份。
- 对每个客户的储蓄月份按时间排序,用「当前月份的数字序号 - 行号」生成分组键——连续的月份这个差值是固定的,以此把连续储蓄的月份归为同一组。
- 按客户和分组键分组,统计每组的月份数量,最后取每个客户的最大数量,就是最长连续储蓄月数。
修正后的SQL代码
WITH monthly_saving AS ( -- 步骤1:将宽表转窄表,提取2024年每个客户的储蓄月份 SELECT CUSTOMER_ID, -- 把每个月的列转成日期,筛选出有储蓄的月份 CASE WHEN JAN24 = 1 THEN DATE '2024-01-01' WHEN FEB24 = 1 THEN DATE '2024-02-01' WHEN MAR24 = 1 THEN DATE '2024-03-01' WHEN APR24 = 1 THEN DATE '2024-04-01' WHEN MAY24 = 1 THEN DATE '2024-05-01' WHEN JUN24 = 1 THEN DATE '2024-06-01' WHEN JUL24 = 1 THEN DATE '2024-07-01' WHEN AUG24 = 1 THEN DATE '2024-08-01' WHEN SEP24 = 1 THEN DATE '2024-09-01' WHEN OCT24 = 1 THEN DATE '2024-10-01' WHEN NOV24 = 1 THEN DATE '2024-11-01' WHEN DEC24 = 1 THEN DATE '2024-12-01' END AS saving_month FROM SAVING_GROWTH -- 确保至少有一个月有储蓄,避免空值 WHERE JAN24=1 OR FEB24=1 OR MAR24=1 OR APR24=1 OR MAY24=1 OR JUN24=1 OR JUL24=1 OR AUG24=1 OR SEP24=1 OR OCT24=1 OR NOV24=1 OR DEC24=1 ), saving_groups AS ( -- 步骤2-3:生成分组键,标记连续储蓄的组 SELECT CUSTOMER_ID, saving_month, -- 用月份序号减去行号,连续月份的差值相同 EXTRACT(MONTH FROM saving_month) - ROW_NUMBER() OVER(PARTITION BY CUSTOMER_ID ORDER BY saving_month) AS group_key FROM monthly_saving WHERE saving_month IS NOT NULL ), group_counts AS ( -- 步骤4:统计每组的连续月数,取最大值 SELECT CUSTOMER_ID, COUNT(*) AS consecutive_months FROM saving_groups GROUP BY CUSTOMER_ID, group_key ) -- 最终结果:每个客户的最长连续储蓄月数 SELECT cb.CUSTOMER_ID, COALESCE(MAX(gc.consecutive_months), 0) AS max_consecutive_saving_months FROM CUSTOMER_BASE cb LEFT JOIN group_counts gc ON cb.CUSTOMER_ID = gc.CUSTOMER_ID GROUP BY cb.CUSTOMER_ID;
补充说明
- 如果
SAVING_GROWTH本身是窄表(每行是客户+月份+储蓄标识),可以跳过第一个CTE,直接用原表过滤2024年且标识=1的记录即可。 COALESCE(MAX(...), 0)是为了处理全年没有任何储蓄的客户,返回0而不是NULL。
内容的提问来源于stack exchange,提问作者user28614546
相关产品推荐
相关产品推荐

