SUM(1)不是计数而是累加常量,语义错位且易误解;COUNT(*)是SQL标准写法,明确表达统计行数意图,执行优化可靠、跨库一致。

SUM(1) 不比 COUNT(*) 更具可读性——它反而容易引发误解,且在绝大多数场景下属于误用。
SUM(1) 的真实行为:它不是“计数”,而是“按行累加常量”
SUM(1) 会为每一行生成值 1,然后把所有 1 加起来。结果数值上等于行数,但语义完全错位:
-
SUM()的本意是对数值求和,参数必须是数值表达式; -
1是合法数值表达式,所以语法通过,执行无错; - 但它掩盖了真实意图:你其实想表达“有多少行”,而不是“把这些 1 加起来”。
这就像用 MAX(1) 表示“存在一行”——技术上返回 1,但别人读到时第一反应是:“你在找最大值?哪来的比较对象?”
为什么有人觉得 SUM(1) “更可读”?常见错觉来源
- 错把“写出来像条件计数”当可读性:比如
SUM(amount > 100)确实比COUNT(CASE WHEN amount > 100 THEN 1 END)短,但这不适用于SUM(1); - 混淆了“结果相同”和“语义等价”:
SUM(1)和COUNT(*)数值相等,但前者暗示“我正在做数值运算”,后者明确说“我在统计行数”; - 在某些旧版 MySQL(5.7 及之前)里,
COUNT(*)在 MyISAM 表上走元数据快,而SUM(1)强制扫描,反而更慢——可读性没提升,性能还受损。
COUNT(*) 是唯一符合 SQL 标准且无歧义的写法
- SQL-92 / SQL:2003 标准明确定义
COUNT(*)为“返回关系的基数(cardinality)”,即行数; - 所有主流数据库(PostgreSQL、SQL Server、Oracle、MySQL 8.0+)都将
COUNT(*)优化为存在性扫描,无需读取列值; -
COUNT(1)虽然也被优化成等价路径,但它仍是COUNT(表达式),语义不如*直接; -
SUM(1)完全不在标准推荐用法中,也没有任何引擎会为它做特殊优化。
真正需要“增强可读性”的地方,是条件计数本身——比如统计支付成功的订单数,应该写 COUNT(CASE WHEN status = 'paid' THEN 1 END),而不是靠 SUM(status = 'paid') 这种 MySQL 特有布尔转整数的隐式行为。
别为了少敲几个字符去迁就一个语义错误的写法。COUNT(*) 四个字符,意思清晰、执行可靠、跨库一致——这才是该坚持的底线。

















