count()统计所有行,count(1)等价于count(),count(列名)仅统计该列非null行;group by要求select中非聚合字段必须出现,null视为独立分组;where在分组前过滤原始数据,having在分组后用聚合函数过滤。

MySQL 统计信息相关面试题,核心落在 COUNT 系列函数的语义差异、GROUP BY 的分组逻辑,以及 HAVING 与 WHERE 的协作关系上。这些不是孤立语法点,而是考察你对 SQL 执行逻辑和数据语义的真实理解。
COUNT(*)、COUNT(1) 和 COUNT(列名) 的区别
三者功能不同,不能简单等价替换:
- COUNT(*):统计结果集的总行数,包括所有行(哪怕整行都是 NULL),不依赖任何列,只看“是否存在这一行”
- COUNT(1):效果与 COUNT(*) 完全一致,1 是常量表达式,不查列值,也不判断 NULL;官方明确说明二者性能无差别
- COUNT(列名):只统计该列值非 NULL的行数;若列允许 NULL,结果可能明显小于 COUNT(*)
例如:一张用户表中,有 100 行记录,但 email 字段有 20 行为 NULL,则 COUNT(*) = 100,COUNT(email) = 80。
GROUP BY 分组统计的关键规则
分组是统计类查询的基础,必须严格遵守语法约束:
- SELECT 子句中,所有非聚合字段必须出现在 GROUP BY 后面;否则报错
- 聚合函数(如 AVG、SUM、MAX、MIN、COUNT)可直接使用,它们作用于每组内部数据
- 支持多字段分组,如 GROUP BY department, gender,表示按部门和性别两个维度组合分组
- NULL 值在分组中会被视为一个独立分组(即所有该列为 NULL 的记录归为一组)
WHERE 和 HAVING 的分工与顺序
两者都用于过滤,但执行时机和能力完全不同:
- WHERE 在分组前执行,只能用原始表字段做条件,不能写聚合函数(如 WHERE AVG(salary) > 5000 是非法的)
- HAVING 在分组后执行,专门用于筛选分组结果,可以且通常需要使用聚合函数(如 HAVING COUNT(*) > 5)
- 执行顺序固定:FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT
典型场景:查“2020 年后入职、且平均薪资超 8000 的部门”,必须 WHERE 先筛时间,再 GROUP BY,最后 HAVING 筛均薪。
常见统计需求的实现思路
面试常考具体业务场景,重点看是否掌握子查询 + JOIN 的组合解法:
- 查“每门课最高分的学生及分数”:先子查询得出每科 max(score),再 JOIN 原表匹配 score 相等的记录
- 查“每个城市对应省份名称及下属城市数量”:JOIN 关联 city 和 province 表,GROUP BY province.id 或 name,用 COUNT(city.id) 统计
- 查“男/女各职业人数”,需同时 GROUP BY sex 和 job,并用 CASE WHEN 或直接分组输出分类统计
这类题本质是验证你能否把业务问题准确拆解为 SQL 的执行阶段:先关联、再分组、后过滤、最后呈现。










