GROUP BY 用于按字段值分组并配合聚合函数统计,非聚合字段必须出现在 GROUP BY 中,HAVING 筛选分组后结果,多字段分组可组合使用并支持 ORDER BY 排序。

MySQL 中 GROUP BY 用于将查询结果按一个或多个字段的值进行分组,使相同值的记录归为一组,通常配合 聚合函数(如 COUNT()、SUM()、AVG()、MAX()、MIN())使用,从而对每组数据进行统计计算。
基本语法与使用规则
GROUP BY 必须出现在 WHERE 子句之后、ORDER BY 和 LIMIT 之前。SELECT 列表中所有 ** 非聚合字段 ** 都必须出现在 GROUP BY 子句中(在严格模式下,MySQL 会报错;否则可能返回非确定性结果)。
- 正确写法:
SELECT dept, COUNT(*) FROM emp GROUP BY dept; - 错误写法(严格模式下):
SELECT dept, name, COUNT(*) FROM emp GROUP BY dept;——name未参与分组且未聚合,结果不可靠
常见组合:聚合函数 + GROUP BY
这是最典型的用法,用于统计每组的数量、总和、平均值等。
- 查每个部门人数:
SELECT dept, COUNT(*) AS cnt FROM emp GROUP BY dept; - 查每个城市的平均薪资:
SELECT city, AVG(salary) AS avg_sal FROM emp GROUP BY city; - 查每种商品类别的最高价格:
SELECT category, MAX(price) FROM products GROUP BY category;
筛选分组结果:HAVING 子句
WHERE 作用于分组前的行,HAVING 作用于分组后的结果,常用来过滤满足条件的组。
- 查员工数超过 5 人的部门:
SELECT dept, COUNT(*) FROM emp GROUP BY dept HAVING COUNT(*) > 5; - 查平均薪资高于 8000 的城市:
SELECT city, AVG(salary) FROM emp GROUP BY city HAVING AVG(salary) > 8000; - 注意:
HAVING可以直接使用聚合函数或别名(如HAVING avg_sal > 8000),但WHERE不可以
多字段分组与排序
可以按多个字段组合分组,顺序影响分组逻辑;通常搭配 ORDER BY 让结果更清晰。
- 按部门和岗位统计人数:
SELECT dept, job, COUNT(*) FROM emp GROUP BY dept, job; - 按年份和月份统计订单数,并按年月升序 排列:
SELECT YEAR(order_time), MONTH(order_time), COUNT(*) FROM orders GROUP BY YEAR(order_time), MONTH(order_time) ORDER BY 1, 2; - 注意:ORDER BY 中可用列名、位置序号(如
ORDER BY 1, 2)或别名
掌握 GROUP BY 的关键是理解“分组后每组只返回一行”,所有非聚合列必须明确属于该组——要么参与分组,要么通过聚合函数处理。实际写 SQL 时,先想清楚“我要按什么分组?每组要算什么?哪些组需要保留?”就能写出准确可靠的语句。