avg()、max()、min() 可在同一 select 中一次性计算,null 自动忽略,空结果返回 null;max()/min() 支持字符串、日期、布尔类型(按字典序或时间序比较),avg() 仅限数值类型;索引可加速 min()/max(),但 avg() 仍需遍历行。

用 AVG()、MAX()、MIN() 一次性查多个聚合值
直接在一条 SELECT 语句里调用多个聚合函数即可,不需要子查询或 UNION。数据库会遍历一次表就完成全部计算,效率没问题。
常见错误是误以为必须分多次查询,或者试图在 WHERE 中直接用 AVG() 过滤(这是非法的,得用 HAVING 配合 GROUP BY)。
SELECT AVG(price), MAX(price), MIN(price) FROM products;- 所有函数作用于同一列时,
NULL值自动被忽略——这点和COUNT(*)不同 - 如果整列都是
NULL,AVG()返回NULL,不是 0;MAX()/MIN()同样返回NULL
对非数值列用 MAX()/MIN() 会发生什么
MAX() 和 MIN() 在字符串列上按字典序比较,在日期列上按时间先后比较,但 AVG() 只支持数值类型(否则报错,如 ERROR: function avg(text) does not exist)。
比如 SELECT MAX(name), MIN(created_at) FROM users; 是合法的,但 AVG(name) 会失败。
- 字符串比较受排序规则(collation)影响,大小写敏感性可能改变结果
- 日期类型(
DATE、TIMESTAMP)能直接用MAX()/MIN(),不用转格式 - 布尔列也能用
MAX()/MIN()(TRUE > FALSE),但意义有限,不推荐依赖
空表或筛选后无数据时的返回值
只要没加 GROUP BY,聚合函数在空结果集上统一返回 NULL,而不是报错或 0。
这意味着你不能靠 COALESCE(AVG(x), 0) 来“兜底”,除非业务逻辑明确允许用 0 代替缺失统计——很多场景下,NULL 才是更准确的语义(表示“无可计算”)。
-
SELECT AVG(score) FROM exams WHERE student_id = 999;→ 返回NULL(不是 0) - 若需转换,用
COALESCE(AVG(score), 0),但要清楚掩盖了数据缺失的事实 -
GROUP BY后某组为空?不会出现——空组根本不出现在结果中
性能与索引注意事项
这三个函数本身不触发全表扫描的额外开销:优化器通常利用索引的最左/最右叶节点快速获取 MIN()/MAX(),而 AVG() 仍需遍历满足条件的行。
但别指望单个索引同时加速三者——MIN() 和 MAX() 对索引方向敏感,AVG() 则完全依赖行数。
- 对
price建普通 B-tree 索引后,MIN(price)和MAX(price)很快,尤其当查询带WHERE category='book'且该字段也在索引中时 - 复合索引
(category, price)能让WHERE category='book' AND MIN(price)高效,但AVG(price)仍需读取所有匹配行 - 没有索引时,三个函数都走全表扫描,但只扫一遍
NULL 的语义,以及字符串列上 MAX() 的排序依赖——这两点在跨环境迁移或对接前端时容易引发隐性 bug。











