Teradata SQL需求:统计指定月份内Prod_cd从A转为B的账户数
解决Teradata中统计A→B单向变更账户的需求
针对你这个统计指定月份内Prod_cd从A单向变更为B的账户需求,我来拆解下实现思路和对应的Teradata SQL代码。核心要抓的就是只有A到B的变更、最终状态为B,且没有反向或来回变更的账户。
假设业务表结构
首先假设你的业务表(比如叫prod_change_log)包含以下核心字段:
account_id:唯一账户IDprod_cd:产品代码(A/B)change_date:变更发生的日期
实现思路
- 先获取每个账户在指定月份内的所有变更记录,同时拉取该账户在指定月份前的最后一次状态(用来判断初始状态是否为A)
- 对每个账户的所有状态记录按时间排序,用窗口函数追踪每一次变更的前后状态
- 过滤出符合以下条件的账户:
- 存在从A到B的变更动作
- 从未出现过从B到A的反向变更
- 最终的产品状态是B
- 初始状态(如果有历史记录)为A,或者当月第一次状态就是A然后变到B
Teradata SQL代码实现
WITH account_change_history AS ( -- 1. 取指定月份的变更记录 + 每个账户在指定月份前的最后一次状态 SELECT account_id, prod_cd, change_date, -- 标记是否是指定月份内的记录 CASE WHEN change_date BETWEEN '2024-03-01' AND '2024-03-31' THEN 1 ELSE 0 END AS is_target_month, -- 按账户分组,按日期排序,获取每条记录的前一个状态 LAG(prod_cd) OVER (PARTITION BY account_id ORDER BY change_date) AS prev_prod_cd FROM prod_change_log WHERE -- 取指定月份及之前的记录,用来判断初始状态 change_date <= '2024-03-31' -- 如果有必要,可以加其他过滤条件,比如有效账户等 ), account_status_trail AS ( -- 2. 整理每个账户的状态轨迹,标记关键变更 SELECT account_id, prod_cd, prev_prod_cd, change_date, is_target_month, -- 获取每个账户的最后状态 LAST_VALUE(prod_cd) OVER (PARTITION BY account_id ORDER BY change_date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS final_prod_cd, -- 标记是否出现过B→A的反向变更 MAX(CASE WHEN prev_prod_cd = 'B' AND prod_cd = 'A' THEN 1 ELSE 0 END) OVER (PARTITION BY account_id) AS has_reverse_change, -- 标记是否出现过A→B的正向变更 MAX(CASE WHEN prev_prod_cd = 'A' AND prod_cd = 'B' THEN 1 ELSE 0 END) OVER (PARTITION BY account_id) AS has_forward_change FROM account_change_history ) -- 3. 过滤符合条件的账户,去重后统计数量 SELECT COUNT(DISTINCT account_id) AS qualified_account_count FROM account_status_trail WHERE -- 有A→B的正向变更 has_forward_change = 1 -- 没有B→A的反向变更 AND has_reverse_change = 0 -- 最终状态是B AND final_prod_cd = 'B' -- 初始状态要么是A,要么当月第一次记录就是A(prev_prod_cd为空且prod_cd='A') AND ( (MIN(prev_prod_cd) OVER (PARTITION BY account_id) IS NULL AND MIN(prod_cd) OVER (PARTITION BY account_id) = 'A') OR MIN(prev_prod_cd) OVER (PARTITION BY account_id) = 'A' ) -- 确保变更发生在指定月份内(如果初始状态是A,当月变B;或者当月内从A变B) AND EXISTS ( SELECT 1 FROM account_change_history ach WHERE ach.account_id = account_status_trail.account_id AND ach.is_target_month = 1 AND ach.prev_prod_cd = 'A' AND ach.prod_cd = 'B' );
代码说明
account_change_historyCTE:拉取指定月份及之前的记录,用LAG获取每个状态的前一个值,方便判断变更方向。account_status_trailCTE:标记每个账户的最终状态、是否有反向变更、是否有正向变更,为后续过滤做准备。- 最终查询:通过多重条件过滤出符合要求的账户,用
COUNT(DISTINCT)得到账户数量。
你可以根据实际的表名、字段名和指定月份(替换代码中的2024-03-01和2024-03-31)调整代码。如果你的表中还有其他需要考虑的逻辑(比如无效变更记录),可以在WHERE条件里补充过滤。
内容的提问来源于stack exchange,提问作者starfly
相关产品推荐
相关产品推荐

