在 SQL 面试题和日常开发中,AVG(平均值) 搭配 GROUP BY 是非常常见的写法。但很多人容易掉进一些陷阱,比如:
结果和预期不一致;
聚合粒度搞错;
NULL 值影响了平均数。
本文就带你拆解这些坑,并提供正确的写法。
1. AVG 的基本用法
AVG(列名) 用来计算某一列的平均值。
最简单的例子:
SELECT AVG(salary) AS avg_salary
FROM employees;
👉 表示统计所有员工的平均薪资。
2. AVG 搭配 GROUP BY
如果我们希望按部门统计平均工资,就需要 GROUP BY:
SELECT department_id, AVG(salary) AS avg_salary
FROM employees
GROUP BY department_id;
👉 每个部门会返回一条记录,显示该部门的平均薪资。
这看起来没问题,但一旦稍有疏忽,就容易出错。
3. 常见陷阱
❌ 陷阱一:SELECT 中多写了非聚合字段
很多人会写成:
SELECT department_id, employee_name, AVG(salary)
FROM employees
GROUP BY department_id;
这在大多数数据库里会报错,因为 employee_name 既不在 GROUP BY 里,也没有被聚合。
👉 解决方案:非聚合字段要么放在 GROUP BY,要么配合聚合函数(比如 MAX(employee_name))。
❌ 陷阱二:GROUP BY 粒度不对
如果你写成:
SELECT department_id, AVG(salary)
FROM employees
GROUP BY department_id, job_title;
👉 结果就不是"部门的平均工资",而是"部门+职位的平均工资"。
很多同学就是因为多写了一个字段,导致结果被细分,统计逻辑完全变了。
❌ 陷阱三:NULL 值影响
在计算平均值时,NULL 会被自动忽略。
例如:
工资列里有些员工工资为 NULL;
AVG 不会算这些 NULL 记录。
这可能会导致和业务预期不一致。比如你想统计"所有员工的平均工资",但实际结果是"有工资数据的员工平均工资"。
👉 解决方案:
如果要把 NULL 当 0 来算,可以用 IFNULL:
SELECT AVG(IFNULL(salary, 0)) AS avg_salary
FROM employees;
4. 面试高频追问
在面试里,面试官可能会追问:
Q1:如何统计每个部门的平均工资,并按平均工资从高到低排序?
SELECT department_id, AVG(salary) AS avg_salary
FROM employees
GROUP BY department_id
ORDER BY avg_salary DESC;
Q2:统计每个部门的平均工资,但只显示平均工资大于 5000 的部门?
SELECT department_id, AVG(salary) AS avg_salary
FROM employees
GROUP BY department_id
HAVING AVG(salary) > 5000;
👉 注意:这里不能用 WHERE,必须用 HAVING,因为 AVG 是聚合结果。
5. 总结
AVG 和 GROUP BY 配合使用时,最容易出错的地方是 非聚合字段 和 分组粒度。
NULL 值默认被忽略,如果业务需要把 NULL 当 0,需要配合 IFNULL 或 COALESCE。
过滤聚合结果时,必须用 HAVING,而不是 WHERE。
面试里常考的延伸是:AVG + GROUP BY + HAVING + ORDER BY 的组合。
📌 一句话记忆:
"AVG 算平均,GROUP BY 定粒度,HAVING 过滤结果,ORDER BY 排序输出。"