SQL多COUNT语句输出异常:指定区间计数与总计数不符问题求助
问题根因
当前条件计数逻辑失效的核心原因:
你使用count(case when ott.tran_date between '01-02-2021' and '24-02-2021' then 1 else 0 end)做区间计数,但count函数仅排除返回值为NULL的行,不会过滤数值为0的非空结果。这里CASE语句不满足条件时返回的是0,属于非空值,所有行都会被count统计,最终结果和count(*)完全相等。
修正方案
二选一即可:
- 将CASE语句的
else 0改为else null,不符合日期条件的行返回NULL,count会自动跳过这类行,仅统计符合区间的行数 - 直接将外层的count替换为sum,用
sum(case when ott.tran_date between '01-02-2021' and '24-02-2021' then 1 else 0 end),满足条件时累加1、不满足时累加0,逻辑更直观,也不会出现统计偏差
其他优化项
- 移除冗余的
distinct:你已经按tam.sol_id分组,分组后每个sol_id仅返回一行,distinct属于完全多余的逻辑,删除即可 - 移除NOT EXISTS子句后多余的右括号:原SQL中关联子查询结束后多写了一个
),会触发语法解析错误 - 补全字段的表别名:当前WHERE子句中
tran_date、acct_cls_flg未指定所属表,一旦多个关联表存在同名字段会触发字段歧义报错,建议全部加上对应表别名 - 避免隐式日期转换:直接用字符串和日期类型字段比较会依赖数据库的NLS日期配置,不同环境下可能出现转换异常,建议显式用日期转换函数(如Oracle的
to_date('日期字符串','dd-mm-yyyy'))声明日期格式 - 替换相关子查询:原SQL中取sol_desc写的是关联子查询,可直接将sol表关联到FROM子句,减少循环查询的性能损耗
修正后可直接运行的示例SQL(适配Oracle语法)
SELECT tam.sol_id || '|' || sol.sol_desc || '|' || COUNT(*) || '|' || SUM(ott.org_tran_amt) || '|' || SUM(CASE WHEN ott.tran_date BETWEEN TO_DATE('01-02-2021','dd-mm-yyyy') AND TO_DATE('24-02-2021','dd-mm-yyyy') THEN 1 ELSE 0 END) FROM ott INNER JOIN tam ON tam.acid = ott.acid INNER JOIN sol ON sol.sol_id = tam.sol_id WHERE tam.gl_sub_head_code IN ('85300','85320','85330','85340','85350','85360','85365','85370','85380','85390','85395') AND ott.tran_date <= TO_DATE('24-02-2021','dd-mm-yyyy') AND ott.del_flg = 'N' AND ott.acct_cls_flg = 'N' AND tam.sol_id IN (SELECT sst.sol_id FROM sst WHERE sst.set_id = 'ROFPZ') AND NOT EXISTS ( SELECT 1 FROM tct WHERE tct.tran_date = ott.tran_date AND TRIM(tct.tran_id) = TRIM(ott.tran_id) AND NVL(ott.org_tran_amt - tct.AMT_OFFSET, 0) = 0 AND tct.entity_cre_flg = 'Y' AND tct.del_flg = 'N' ) GROUP BY tam.sol_id, sol.sol_desc;
修正后最后一列将仅统计2021年2月1日-2月24日区间内的交易数,数值会自然小于等于总交易计数,符合业务要求。
内容的提问来源于stack exchange,提问作者erdeepak
相关产品推荐
相关产品推荐

