SQL分组统计核心是GROUP BY划分数据组后用聚合函数计算,需明确“按什么分”和“算什么”;非聚合字段必须出现在GROUP BY中;WHERE用于分组前过滤,HAVING用于分组后筛选;NULL默认自成一组;多字段分组按组合唯一性处理。

SQL分组统计核心就一条:先用 GROUP BY 划分数据组,再用聚合函数(如 COUNT、SUM、AVG)对每组计算。关键不是写出来,而是想清楚“按什么分”和“算什么”,否则结果错得悄无声息。
明确分组字段,别漏掉非聚合列
SELECT 里只要出现非聚合字段,就必须出现在 GROUP BY 后面。比如想看每个部门的平均工资:
✅ 正确:SELECT dept, AVG(salary) FROM emp GROUP BY dept;
❌ 错误(报错或结果不可靠):SELECT dept, name, AVG(salary) FROM emp GROUP BY dept; // name 没分组,数据库通常直接报错
很多新手会把所有 SELECT 字段都塞进 GROUP BY,看似能跑通,但逻辑混乱——比如加了 employee_id 就等于没分组。记住:GROUP BY 的字段,就是你分析维度的“最小单位”。
WHERE 和 HAVING 别混用
WHERE 是分组前过滤,作用于原始行;HAVING 是分组后筛选,作用于聚合结果。
- 查“人数超过5人的部门” → 用 HAVING:SELECT dept, COUNT(*) FROM emp GROUP BY dept HAVING COUNT(*) > 5;
- 查“只统计2023年入职的员工” → 用 WHERE:SELECT dept, COUNT(*) FROM emp WHERE hire_date >= '2023-01-01' GROUP BY dept;
- 如果写成 WHERE COUNT(*) > 5,语法直接报错——因为 WHERE 看不到聚合值。
空值(NULL)默认参与分组,常被忽略
dept 为 NULL 的记录会自成一组。如果你没意识到,可能漏掉一批数据,或误以为“没统计到”。可主动处理:
- 排除空值:WHERE dept IS NOT NULL GROUP BY dept
- 把空值归为一类:SELECT COALESCE(dept, '未知部门') AS dept_group, COUNT(*) FROM emp GROUP BY COALESCE(dept, '未知部门')
多字段分组注意顺序和组合逻辑
GROUP BY dept, city 表示“先按部门,再按城市”分组,等价于按 (dept + city) 的唯一组合分组。不是分别分组两次。
- 想看“每个城市每个部门的平均薪资” → GROUP BY city, dept
- 不要写成 GROUP BY city GROUP BY dept(语法错误)
- 也不建议在 SELECT 中只写 city 或只写 dept 而 GROUP BY 两个字段(除非用 ANY_VALUE() 等特殊函数,但需确认 SQL 模式支持)
基本上就这些。不复杂,但容易忽略细节。写完多问一句:我分的是我想分的组吗?过滤是在分组前还是后?NULL 去哪了?答案清楚了,结果才稳。










