位置:首页 > SQL > SQL 中如何统计满足条件与不满足条件的数据

SQL 中如何统计满足条件与不满足条件的数据

时间:2026-08-25  |  作者:实验室老王  |  阅读:0

需运用两个SUM(CASE WHEN ... THEN 1 ELSE 0 END)来分别统计满足条件与不满足条件的行数,而非COUNT(CASE WHEN)加COUNT(*)做减法。因为后者会遗漏NULL行,且无法区分false与unknown;还应显式覆盖NULL分支(如status IS NULL),以此保证语义的准确性和结果的可靠性。

SQL中如何统计满足条件与不满足条件的数据

直接用 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 NULLstatus <=> '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中添加这一分支。

免责声明:文中图文均来自网络,如有侵权请联系删除,心愿游戏发布此文仅为传递信息,不代表心愿游戏认同其观点或证实其描述。

相关文章

更多

精选合集

更多

大家都在玩

热门话题

大家都在看

更多