mysql如何使用聚合函数_mysql sum、avg、max、min示例

来源:这里教程网 时间:2026-02-28 20:46:20 作者:

sum、avg、max、min 基本用法和 NULL 处理

MySQL 聚合函数默认忽略

NULL
值,这点必须牢记——比如
SUM
不会把
NULL
当作 0 加,而是直接跳过;
AVG
计算时分母是**非 NULL 行数**,不是总行数。如果整列都是
NULL
SUM
AVG
返回
NULL
MAX
/
MIN
同样返回
NULL

常见误操作:在没加

WHERE
GROUP BY
的情况下对全表用聚合函数,结果只有一行,容易误以为“没生效”。实际是正常行为——聚合函数天然压缩结果集。

SUM(col)
:只接受数值型列,字符串会隐式转为数字(如
'12abc'
12
'abc'
0
AVG(col)
:结果类型自动提升(如
INT
列返回
DECIMAL(10,2)
),精度可由
ROUND(AVG(col), 2)
控制
MAX(col)
MIN(col)
支持数值、字符串、日期,字符串按字典序比较(
'Z' > 'a'
因 ASCII 值更小)

GROUP BY 配合聚合函数的典型陷阱

一旦用了

GROUP BY
SELECT
列表里所有**非聚合字段必须出现在
GROUP BY
子句中**,否则 MySQL 5.7+ 默认报错(
sql_mode=ONLY_FULL_GROUP_BY
开启)。这是最常触发
ERROR 1055
的场景。

示例错误写法:

SELECT user_id, name, SUM(amount) FROM orders GROUP BY user_id
——
name
未被分组也未聚合,MySQL 拒绝执行。

安全写法:补全
GROUP BY user_id, name
,或改用聚合取值,如
MAX(name)
注意
GROUP BY
对 NULL 的处理:所有
NULL
值视为同一组
性能提示:
GROUP BY
字段最好有索引,否则可能触发临时表 + 文件排序

WHERE 和 HAVING 的分工必须分清

WHERE
过滤的是**原始行**,
HAVING
过滤的是**分组后的聚合结果**。混淆两者会导致逻辑错误或语法报错。

比如想查“订单总额超 1000 的用户”,必须用

HAVING SUM(amount) > 1000
;若写成
WHERE SUM(amount) > 1000
,MySQL 直接报错
Invalid use of group function

WHERE
可用列:原表任意字段,支持索引加速
HAVING
可用内容:聚合函数结果、
GROUP BY
中的字段、别名(如
SELECT SUM(x) AS s FROM t GROUP BY y HAVING s > 10
执行顺序:
WHERE
→ 分组 → 聚合 →
HAVING
,所以
HAVING
无法替代
WHERE
做行级过滤

COUNT(*)、COUNT(col)、COUNT(1) 的真实差异

很多人以为

COUNT(1)
COUNT(*)
快,其实 MySQL 优化器对三者等价处理,最终都走相同执行路径。真正影响性能的是是否能用上索引。

COUNT(*)
统计所有行(包括含
NULL
的行);
COUNT(col)
只统计该列非
NULL
的行数;
COUNT(1)
等同于
COUNT(*)
,因为
1
永不为
NULL

想统计“有邮箱的用户数”:用
COUNT(email)
想统计“用户总数”(不管字段是否为空):用
COUNT(*)
MyISAM 表上
COUNT(*)
是 O(1),InnoDB 必须扫描(除非覆盖索引)

聚合函数本身不难,但和

GROUP BY
NULL
、执行顺序搅在一起时,最容易在边界 case 上翻车——比如空表返回
NULL
而不是
0
,或者
HAVING
里误用未聚合字段。这些地方不报错,但结果不对,调试起来反而更费时间。

相关推荐