avg()仅计算非null值,忽略null记录;参数须为数值类型;group by下按组计算;where过滤聚合前行,having过滤聚合后结果;不可嵌套使用。

AVG() 函数的基本用法和 NULL 处理
AVG() 只计算非 NULL 值,自动跳过字段中为 NULL 的记录。这点容易被忽略,导致结果比预期偏高——比如你有一张用户订单表,amount 字段部分为空,直接 AVG(amount) 会把空单子完全排除,算的是“有金额订单”的平均值,不是“所有订单”的平均金额(后者需先补 0 或明确业务定义)。
常见错误现象:SELECT AVG(score) FROM students; 返回 NULL —— 这说明整列全是 NULL 或无数据,不是函数出错,而是没可计算值。
- 若想把
NULL当0参与计算,写成AVG(COALESCE(score, 0)) - 若只想统计“有效评分”,保持默认行为即可,但必须确认业务是否允许丢弃
NULL -
AVG()要求参数是数值类型,对字符串或日期直接用会报错,如AVG(name)→ERROR: function avg(text) does not exist
GROUP BY 下的 AVG 需明确聚合粒度
在分组场景下,AVG() 是按每组单独计算,不是全表平均再分配。比如按部门查平均薪资:SELECT dept, AVG(salary) FROM employees GROUP BY dept;,结果里每个部门一个平均值,互不影响。
容易踩的坑:误把非分组字段放进 SELECT 列表,例如 SELECT dept, name, AVG(salary) —— 大多数数据库(PostgreSQL、SQL Server)会直接报错 column "name" must appear in the GROUP BY clause;MySQL 8.0+ 默认也开启严格模式,同样拒绝。
- 只选分组字段 + 聚合函数,如
SELECT dept, AVG(salary), COUNT(*) - 若还需看某个人名,得用子查询或窗口函数,不能硬塞进
GROUP BY查询里 - 注意浮点精度:
AVG()返回类型通常和输入一致,整数列可能截断小数,如AVG(1,2,3)在某些引擎返回2而非2.0;需要小数时显式转换:AVG(CAST(salary AS DECIMAL(10,2)))
WHERE 和 HAVING 对 AVG 的影响完全不同
WHERE 过滤的是参与聚合的原始行,HAVING 过滤的是聚合后的结果行。这是理解 AVG() 行为的关键分水岭。
举例:查“平均薪资超 15000 的部门”必须用 HAVING:SELECT dept, AVG(salary) FROM employees GROUP BY dept HAVING AVG(salary) > 15000;。如果写成 WHERE AVG(salary) > 15000,会报错 ERROR: aggregate functions are not allowed in WHERE。
-
WHERE salary > 5000先筛掉低薪员工,再算各部门平均 —— 改变分子分母 -
HAVING AVG(salary) > 15000是先算出所有部门平均值,再过滤结果集 —— 不影响计算过程 - 两者可共存:
WHERE status = 'active' HAVING AVG(salary) > 15000,顺序不可逆
嵌套 AVG 或配合窗口函数时要注意执行顺序
SQL 执行顺序是 FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY,所以 AVG() 在 SELECT 阶段才计算,无法在 WHERE 或 GROUP BY 中引用别名(如 SELECT AVG(x) AS avg_x WHERE avg_x > 10 必报错)。
想实现“查高于全局平均的记录”,得用子查询或窗口函数:SELECT * FROM sales WHERE amount > (SELECT AVG(amount) FROM sales); 或 SELECT *, AVG(amount) OVER() AS global_avg FROM sales WHERE amount > global_avg(后者需注意:窗口函数在 SELECT 阶段执行,但别名不能用于同一层 WHERE)。
- 子查询方式最兼容,但多次扫描表可能慢
- 窗口函数更高效,但
WHERE不能直接用窗口别名,得写成WHERE amount > AVG(amount) OVER() - 嵌套
AVG(AVG(x))没有意义,SQL 不支持对聚合结果再聚合,会报语法错误
实际用的时候,先想清楚:你要平均的是哪些行?要不要包含 NULL?结果要按什么维度呈现?这三个问题没理清,AVG() 写得再对,语义也可能跑偏。










