count(*)统计所有行(含null),count(列名)只统计该列非null行;sum/avg全null时返回null而非0;group by后select列须为分组字段或聚合表达式;聚合函数不可嵌套。

count() 统计行数时 NULL 值怎么处理
COUNT() 只统计非 NULL 的值,但行为取决于写法:COUNT(*) 统计所有行(包括含 NULL 的行),COUNT(列名) 只统计该列非 NULL 的行。
- 常见错误:用
COUNT(字段)想统计总记录数,结果比预期少——因为字段里有NULL - 场景:查用户表里填了手机号的人数,用
COUNT(phone);查注册总人数,必须用COUNT(*) - 性能影响:
COUNT(*)在 InnoDB 里可能走索引统计(如主键索引),而COUNT(字段)必须读取实际列值判断是否为NULL,更慢
sum() 和 avg() 遇到全 NULL 结果是 NULL 而不是 0
SUM() 和 AVG() 对空结果集或全 NULL 列返回 NULL,不是 0 或 0.0。这在报表、前端展示时容易触发空值报错或显示异常。
- 常见错误:前端直接渲染
avg(score),结果是NULL,JS 报Cannot read property 'toFixed' of null - 解决办法:用
COALESCE(SUM(列), 0)或IFNULL(AVG(列), 0)显式转默认值 - 注意:
AVG()自动跳过NULL,但不会跳过0——如果业务中“未评分”存为0,会拉低均值,得确认数据语义
group by 后 select 列必须是分组字段或聚合表达式
MySQL 5.7 严格模式下,SELECT 中出现未聚合、也未出现在 GROUP BY 中的列,会报错:Expression #2 of SELECT list is not in GROUP BY clause。
- 常见错误:写
SELECT user_id, name, COUNT(*) FROM orders GROUP BY user_id,name不在GROUP BY里,且没聚合,直接报错 - 正确做法:要么加进
GROUP BY(如GROUP BY user_id, name),要么用聚合函数包裹(如MAX(name)) - 兼容性提醒:MySQL 8.0 默认开启严格模式,老项目迁移到新版本常在这里翻车;临时关 strict mode 不解决问题,只掩盖逻辑缺陷
聚合函数不能嵌套,比如 count(sum(x)) 是语法错误
MySQL 不允许把一个聚合函数作为另一个聚合函数的参数,COUNT(SUM(price)) 这类写法会直接报 Invalid use of group function。
- 常见错误:想“统计每个品类销售额大于 1000 的订单数”,误写成
SELECT category, COUNT(SUM(amount)) FROM orders GROUP BY category HAVING SUM(amount) > 1000 - 正确思路:先用子查询或窗口函数算出每条记录的聚合中间态,再外层统计;例如用
HAVING SUM(amount) > 1000过滤分组,再用外部COUNT(*)包一层(需嵌套查询) - 替代方案:MySQL 8.0+ 可用窗口函数,如
COUNT(*) OVER (PARTITION BY category),但注意它不等价于二次聚合,得看具体需求
聚合函数看着简单,但 NULL 处理、分组边界、嵌套限制这几处,一不留神就产出错误结果,而且不容易被测试覆盖到——尤其当数据里开始出现空值或边缘分组时。










