SQL 中如何统计满足条件与不满足条件的数据
时间:2026-08-25 | 作者:实验室老王 | 阅读:0需运用两个SUM(CASE WHEN ... THEN 1 ELSE 0 END)来分别统计满足条件与不满足条件的行数,而非COUNT(CASE WHEN)加COUNT(*)做减法。因为后者会遗漏NULL行,且无法区分false与unknown;还应显式覆盖NULL分支(如status IS NULL),以此保证语义的准确性和结果的可靠性。
直接用 SUM(CASE WHEN) 统计满足/不满足条件的两组数量
要同时拿到“满足条件”和“不满足条件”的行数,最稳的方式是写两个 SUM(CASE WHEN ... THEN 1 ELSE 0 END):一个统计真值,一个统计假值。别用 COUNT(CASE WHEN ... THEN 1 END) 去算满足数,再用 COUNT(*) - 上面结果 算不满足——这在有 NULL 或分组时容易错漏。
SUM(CASE WHEN status = 'paid' THEN 1 ELSE 0 END)→ 满足条件的计数(含显式 0)SUM(CASE WHEN status != 'paid' OR status IS NULL THEN 1 ELSE 0 END)→ 不满足条件的计数(必须覆盖 NULL)- 如果字段定义为
NOT NULL,可简化为SUM(CASE WHEN status != 'paid' THEN 1 ELSE 0 END) - 避免写成
COUNT(CASE WHEN status = 'paid' THEN 1 END)+COUNT(*) - ...:当该字段本身含 NULL 时,COUNT(*)包含 NULL 行,但COUNT(CASE...)不包含,差值就不等于“不满足”
为什么不能只靠 COUNT(CASE WHEN) + COUNT(*) 推导
表面看 COUNT(*) 减去 COUNT(CASE WHEN cond THEN 1 END) 像能得出“不满足”数,但实际会漏掉 NULL 行,且无法区分“明确为 false”和“未知(NULL)”。
- 假设
status列有值'paid'、'pending'和NULL,那么COUNT(CASE WHEN status = 'paid' THEN 1 END)只计 paid 行;COUNT(*)计全部三类;差值 = pending + NULL 行数,但你无法知道其中多少是 NULL - 业务上常需分开统计:
unpaid_count(明确 != paid)、unknown_status_count(NULL),这时必须显式写分支 - 若强行用减法,后续做百分比时分母错位(比如除以
COUNT(*)却把 NULL 当作 “不满足”,语义就歪了)
分组场景下统计每组的满足/不满足比例
在 GROUP BY 后算每组内满足与不满足的占比,推荐用 A VG(CASE WHEN ... THEN 1.0 ELSE 0 END),它天然规避除零、自动忽略 NULL(只要你写了 ELSE 0),比手写除法更安全。
A VG(CASE WHEN score >= 60 THEN 1.0 ELSE 0 END)→ 直接返回该组及格率(小数)- 等价于
SUM(CASE WHEN score >= 60 THEN 1 ELSE 0 END) * 1.0 / COUNT(*),但不用处理COUNT(*) = 0的报错 - 如果想保留整数百分比,套一层
ROUND(... * 100, 0)即可 - 注意:MySQL/SQL Server 需显式写
1.0,PostgreSQL 支持A VG(score >= 60)(bool 自转 float)
跨数据库兼容写法的关键细节
所有主流数据库都支持 SUM(CASE WHEN ... THEN 1 ELSE 0 END),但日期、字符串、NULL 的处理细节极易踩坑。
- 日期年份提取:
YEAR(order_date)(MySQL/SQL Server)、EXTRACT(YEAR FROM order_date)(PostgreSQL)、strftime('%Y', order_date)(SQLite) - 字符串比较:用单引号
'active',别用双引号(PostgreSQL 中双引号是标识符) - NULL 安全判断:写
status IS NULL或status <=> 'paid'(MySQL 空值安全等于),别依赖=或!= - 性能提示:多个条件并列统计时,
SUM(CASE ...)只扫一遍表;拆成多个WHERE子查询会反复扫描,大数据量下明显变慢
在实际应用中,有一点常常被忽视,那就是NULL分支是否需要显式覆盖。虽然它不会报错,但结果可能会在无声无息中发生偏移。所以,在编写代码后,不妨先用 SELECT COUNT(*) FILTER (WHERE col IS NULL)(PostgreSQL)或者 A VG(CASE WHEN col IS NULL THEN 1.0 ELSE 0 END) 来查询一下NULL的比例,然后再决定是否要在CASE中添加这一分支。
免责声明:文中图文均来自网络,如有侵权请联系删除,心愿游戏发布此文仅为传递信息,不代表心愿游戏认同其观点或证实其描述。
相关文章
更多-
- 迅捷路由器怎么调信号最强,设置时要注意什么?
- 时间:2026-08-27
-
- vivo浏览器怎么卸不掉?原因和解决方法在这里
- 时间:2026-08-27
-
- OPPO R11s黑屏了,怎么强制恢复出厂设置?
- 时间:2026-08-27
-
- 飞利浦显示器包装盒有生产日期和保修期吗?怎么看?
- 时间:2026-08-27
-
- 联想新平板开机必须联网吗?怎么做?
- 时间:2026-08-27
-
- 平板横竖屏切换设置与问题解决
- 时间:2026-08-27
-
- 移动电源容量怎么测?要准备哪些工具?
- 时间:2026-08-27
-
- 荣耀90 Pro防水吗?防水级别多少?怎么用才安全
- 时间:2026-08-27
精选合集
更多大家都在玩
大家都在看
更多-
- 糖尿病完全不能吃糖吗
- 时间:2026-09-15
-
- 蚂蚁庄园小课堂2026年9月16日最新题目答案
- 时间:2026-09-15
-
- 小鸡答题今天的答案是什么2026年9月16日
- 时间:2026-09-15
-
- 蚂蚁庄园每日答题答案2026年9月16日
- 时间:2026-09-15
-
- 以下哪种粮食是酿造绍兴黄酒的主要原料 蚂蚁庄园今日答案9月16日
- 时间:2026-09-15
-
- 劝学名句“及时当勉励,岁月不待人”出自哪位诗人 蚂蚁庄园今日答案9.16
- 时间:2026-09-15
-
- 蚂蚁庄园今天答题答案2026年9月16日
- 时间:2026-09-15
-
- 蚂蚁庄园答题今日答案2026年9月16日
- 时间:2026-09-15
