如何高效统计可空列中Null、0、1及2+值的出现次数?
高效统计可空非负int列的各类值出现次数
嘿,这个需求我经常碰到,要高效搞定这类分情况的计数,核心就是只扫描一次表,避免多次查询带来的额外IO开销。下面给你几种通用且高效的实现方式,适配不同主流数据库:
通用SQL写法(适用于所有支持标准SQL的数据库)
最稳妥的方式是用CASE WHEN配合聚合函数,一次性算出所有类别的次数:
方式1:用COUNT统计
COUNT会忽略NULL值,所以我们让符合条件的行返回1,不符合的返回NULL,就能自动统计次数:
SELECT COUNT(CASE WHEN your_col IS NULL THEN 1 END) AS null_count, COUNT(CASE WHEN your_col = 0 THEN 1 END) AS zero_count, COUNT(CASE WHEN your_col = 1 THEN 1 END) AS one_count, COUNT(CASE WHEN your_col >= 2 THEN 1 END) AS ge_two_count FROM your_table;
方式2:用SUM统计
另一种思路是让符合条件的行返回1,不符合的返回0,用SUM累加:
SELECT SUM(CASE WHEN your_col IS NULL THEN 1 ELSE 0 END) AS null_count, SUM(CASE WHEN your_col = 0 THEN 1 ELSE 0 END) AS zero_count, SUM(CASE WHEN your_col = 1 THEN 1 ELSE 0 END) AS one_count, SUM(CASE WHEN your_col >= 2 THEN 1 ELSE 0 END) AS ge_two_count FROM your_table;
各数据库专属简化写法
如果用特定数据库,还能让代码更简洁:
MySQL/MariaDB
可以用IF函数替代CASE WHEN,语法更紧凑:
SELECT SUM(IF(your_col IS NULL, 1, 0)) AS null_count, SUM(IF(your_col = 0, 1, 0)) AS zero_count, SUM(IF(your_col = 1, 1, 0)) AS one_count, SUM(IF(your_col >= 2, 1, 0)) AS ge_two_count FROM your_table;
PostgreSQL
PostgreSQL支持FILTER子句,可读性更强:
SELECT COUNT(*) FILTER (WHERE your_col IS NULL) AS null_count, COUNT(*) FILTER (WHERE your_col = 0) AS zero_count, COUNT(*) FILTER (WHERE your_col = 1) AS one_count, COUNT(*) FILTER (WHERE your_col >= 2) AS ge_two_count FROM your_table;
SQL Server
除了通用写法,还可以用IIF函数简化:
SELECT SUM(IIF(your_col IS NULL, 1, 0)) AS null_count, SUM(IIF(your_col = 0, 1, 0)) AS zero_count, SUM(IIF(your_col = 1, 1, 0)) AS one_count, SUM(IIF(your_col >= 2, 1, 0)) AS ge_two_count FROM your_table;
性能优化提示
- 上述所有写法都只扫描一次表,是这类需求中性能最优的方案,远胜多次单独查询(比如四个
SELECT COUNT(*) FROM ... WHERE ...)。 - 如果你的表数据量极大,可以考虑给
your_col建立覆盖索引(如果表中只有这一列需要统计,或者索引包含必要字段),让数据库直接扫描索引而非全表,进一步提升速度。
内容的提问来源于stack exchange,提问作者quester
相关产品推荐
相关产品推荐

