聚合函数陷阱:AVG 和 GROUP BY 搭配使用注意点

在 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 排序输出。"

相关推荐
蕨蕨学AI几秒前
【Wolfram语言】45.2 真实数据集
java·数据库
The Sheep 20238 分钟前
MongoDB与.Net6
数据库·mongodb
BryceBorder17 分钟前
SCAU--数据库
数据库·oracle·dba
有味道的男人22 分钟前
京东关键词API接口获取
数据库
罗光记39 分钟前
《人工智能安全治理研究报告(2025年)发布
数据库·其他·百度·新浪微博
202321336054 刘1 小时前
Linux常用命令分类整理
linux·运维·数据库
Q741_1471 小时前
海致星图招聘 数据库内核研发实习生 一轮笔试 总结复盘(2) 作答语言:C/C++ 哈夫曼编码 LRU
c语言·数据库·c++·算法·笔试·哈夫曼编码·哈夫曼树
齐 飞1 小时前
快速删除mysql表中所有数据-TRUNCATE TABLE
数据库·mysql
想摆烂的不会研究的研究生1 小时前
每日八股——Redis(2)
数据库·redis·缓存
optimistic_chen1 小时前
【Redis系列】主从复制
linux·数据库·redis·缓存·中间件·命令行·主从复制