从3张表派生SPEED_UPGRADE与TV_PACKAGE字段的SQL查询计数异常优化请求
问题分析与SQL优化方案
你的核心问题出在用count()统计符合条件的记录上——count()函数会统计所有非NULL的结果,哪怕你的CASE语句返回0(这是一个非空值),它也会被计入总数,所以最终得到的是所有记录的数量,而非符合条件的目标记录数。
解决思路
把count()换成sum()就能直接解决问题:
sum()会对CASE返回的1和0做累加,符合条件的加1,不符合的加0,最终结果就是你要的有效记录数。- 你也可以选择让
CASE在不满足条件时返回NULL(去掉ELSE 0),这样count()会自动忽略NULL值,但sum()的写法更直观易懂。
优化后的SQL(格式化+修正统计逻辑)
我还帮你把SQL做了格式化拆分,提升可读性,同时简化了重复的时间判断逻辑:
WITH filtered_base AS ( SELECT * FROM P0_view.edw_v_fct_subscriber_household_base WHERE subscriber_status_cd = 'Active' AND billed_customer_id = '-1' AND household_id > 0 AND household_base_dt = '2021-11-09' ), voucher_processed AS ( SELECT f.*, a.START_DT, -- 提前处理END_DT的默认值,避免重复计算 COALESCE(a.END_DT, CAST('9999-12-31 00:00:00' AS TIMESTAMP FORMAT 'Y4-MM-DDBHH:MI:SS')) AS ADJ_END_DT, b.VOUCHER_TYPE_CD FROM filtered_base f RIGHT JOIN P0_VIEW.EDW_V_FCT_FIXED_VOUCHER_REDEEMED a ON f.CUSTOMER_ID = a.CUSTOMER_ID LEFT JOIN P0_VIEW.EDW_V_DIM_FIXED_VOUCHER b ON a.FIXED_VOUCHER_ID = b.FIXED_VOUCHER_ID ) SELECT <few columns>, -- 替换成你实际需要的分组列 -- 用SUM替代COUNT统计符合条件的记录 SUM(CASE WHEN CAST('2021-11-09 00:00:00' AS TIMESTAMP(0)) BETWEEN START_DT AND ADJ_END_DT AND VOUCHER_TYPE_CD = 'SPEED' THEN 1 ELSE 0 END) AS SPEED_UPGRADE, SUM(CASE WHEN CAST('2021-11-09 00:00:00' AS TIMESTAMP(0)) BETWEEN START_DT AND ADJ_END_DT AND VOUCHER_TYPE_CD = 'TV' THEN 1 ELSE 0 END) AS TV_PACKAGE FROM voucher_processed GROUP BY 1,2,3,4,5,6,7,8,9;
额外优化说明
- 用CTE拆分逻辑:把基础数据过滤、关联字段预处理拆成两个CTE,让代码结构更清晰,后续维护更方便。
- 简化重复计算:提前计算好调整后的结束时间
ADJ_END_DT,避免在两个CASE里重复写相同的表达式。 - 可读性提升:通过换行、缩进梳理SQL的逻辑层次,一眼就能看懂各个环节的作用。
内容的提问来源于stack exchange,提问作者Neha Bhatt
相关产品推荐
相关产品推荐

