sql分组统计需严格遵循四步逻辑:先用WHERE筛选原始行(仅支持原始字段),再用GROUP BY划分数据组(非聚合列须全部列出),接着用HAVING筛选组结果(可使用聚合函数),最后用聚合函数与ORDER BY汇总排序。

SQL分组统计不是“写个GROUP BY就完事”,而是一套有严格执行顺序、明确语义边界和常见陷阱的逻辑体系。掌握它,关键在理清“谁先筛、谁归组、谁后筛、谁来汇总”这四步关系。
分组前:用WHERE筛选原始行
WHERE是第一道过滤关,作用于分组之前,只能使用原始字段,不能用AVG、count这类聚合函数。
- 比如查“2024年入职的员工”,写 WHERE hire_date >= ‘2024-01-01’
- 如果误写成 WHERE AVG(sal) > 5000,直接报错——因为此时还没分组,更没算出平均值
- 它决定“哪些人能进组”,不参与后续分组计算
分组中:用GROUP BY划定数据块
GROUP BY按指定列值把行聚合成一个个逻辑组,每组对应select中一个结果行。
- 分组列必须出现在SELECT列表中(除非被聚合函数包裹)
- 多字段分组如 GROUP BY deptno, job,表示先按部门再按职位细分
- NULL值会被单独归为一组(不是被忽略),如需合并处理可用 COALESCE(deptno, 0)
- SELECT里所有非聚合列,都得在GROUP BY中完整列出,否则语法报错
分组后:用HAVING筛选组结果
HAVING是第二道过滤关,作用于分组完成、聚合计算之后,可安全使用AVG、COUNT等函数。
- 比如“只显示平均工资超3000的职位”,写 HAVING AVG(sal) > 3000
- 它判断的是“哪个组该留下”,不是哪个人——所以条件里出现的聚合值,天然代表整个组的特征
- HAVING必须紧跟GROUP BY之后,不能放在WHERE前面或ORDER BY后面
汇总与呈现:聚合函数+ORDER BY收尾
聚合函数(COUNT、SUM、AVG、MAX、MIN)是分组统计的“计算引擎”,配合ORDER BY让结果更易读。
- COUNT(*)统计组内行数;COUNT(sal)只统计sal非NULL的行数
- AVG、SUM、MAX、MIN自动忽略NULL,无需额外处理
- 排序建议用别名,如 ORDER BY total_amount DESC,比重复写SUM(amount)更清晰安全
- 若需补全无数据的组(如某部门没人),要用LEFT JOIN+GROUP BY,而非单纯靠HAVING
基本上就这些。逻辑链清晰了,写起来不绕,调起来不懵,查起来不漏。