sql分组统计核心是GROUP BY搭配聚合函数,关键在于明确“按什么分”“算什么”“怎么过滤”;需注意非聚合字段必须出现在GROUP BY中,WHERE用于分组前行过滤,HAVING用于分组后组过滤,支持多字段联合分组及NULL值处理,结果可排序和限制输出。

SQL分组统计核心就一条:用 GROUP BY 搭配聚合函数(如 count、SUM、AVG、MAX、MIN),把数据按指定字段“归堆”,再对每堆算一个汇总值。关键不是语法多难,而是搞清“按什么分”“算什么”“怎么过滤”这三步逻辑。
一、基础写法:先分组,再聚合
分组统计必须出现在 select 子句中,且所有非聚合字段都得出现在 GROUP BY 后面。否则数据库会报错(比如 mysql 严格模式下)。
- 正确写法:SELECT department, COUNT(*) FROM employees GROUP BY department;
- 错误写法:SELECT department, name, COUNT(*) FROM employees GROUP BY department;(name 不在 GROUP BY 中,也没聚合,非法)
二、带条件的分组:WHERE 和 HAVING 别混用
WHERE 在分组前筛选原始行(比如只统计在职员工);HAVING 在分组后筛选分组结果(比如只看人数超5人的部门)。
- WHERE 过滤的是“行”,HAVING 过滤的是“组”
- HAVING 后可直接用聚合函数,WHERE 不可以(比如 HAVING AVG(salary) > 8000 是合法的,WHERE AVG(salary) > 8000 会报错)
- 典型组合:SELECT dept, AVG(salary) FROM emp WHERE status = ‘active’ GROUP BY dept HAVING COUNT(*) >= 3;
三、多字段分组 & 空值处理要留心
按多个字段分组时,GROUP BY 后写逗号分隔的字段,代表“联合分组”。比如按部门+岗位统计人数,相同部门和相同岗位才归为一组。
- SELECT department, position, COUNT(*) FROM employees GROUP BY department, position;
- 注意 NULL 值:NULL 和 NULL 在 GROUP BY 中被视为相同,会被分到同一组。如果想单独处理空值,可用 COALESCE 或 CASE 预处理,例如 GROUP BY COALESCE(department, ‘未知部门’);
四、配合排序与限制输出更实用
分组结果常需排序展示(比如看销售额Top 3的地区),这时 ORDER BY 要放在 GROUP BY 之后、LIMIT 之前。ORDER BY 可用别名或聚合表达式。
- SELECT region, SUM(amount) AS total FROM orders GROUP BY region ORDER BY total DESC LIMIT 3;
- 也可按分组字段排序:ORDER BY region ASC
- 注意:MySQL 8.0+ 支持窗口函数,如需“每组内排名”或“累计求和”,可用 RANK() OVER (PARTITION BY …),但那已超出基础分组范畴
基本上就这些。分组统计不复杂但容易忽略细节,动手写几遍、故意试错几次(比如漏 GROUP BY、错用 WHERE/HAVING),比死记语法管用得多。