[42000][1055] Expression #1 of ORDER BY clause is not in GROUP BY clause and contains nonaggregated column
SELECT @@sql_mode;
查看当前会话的 sql_mode(sql_mode 是 MySQL 中的一个重要系统变量,用于定义 MySQL 执行 SQL 语句时的 语法校验、数据校验以及行为模式,它决定了 MySQL 对 SQL 标准的遵循程度、数据验证规则和特殊语法的支持情况。)
ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
ONLY_FULL_GROUP_BY 的作用
假设你有一张学生表 student,数据如下:
| 班级(class) | 姓名(name) | 成绩(score) |
|---|---|---|
| 一班 | 张三 | 80 |
| 一班 | 李四 | 90 |
| 二班 | 王五 | 85 |
现在你想查询 "每个班级的最高成绩",写了这样的 SQL:
SELECT class, name, MAX(score) FROM student GROUP BY class;
没有 ONLY_FULL_GROUP_BY 时会发生什么?
MySQL 会按 class 分组(分成 "一班" 和 "二班" 两组),但 name 列既不在 GROUP BY 中,也没有用聚合函数(如 MAX())处理。
-
一班有两个学生(张三、李四),MySQL 会随机选一个名字(比如张三)显示,结果可能是:
class name MAX(score) 一班 张三 90 二班 王五 85
这就出现了问题:结果中的 name 是不确定的(换个时间执行可能选李四),而你想要的其实只是 "班级+最高成绩",姓名在这里是多余且混乱的。
启用 ONLY_FULL_GROUP_BY 后会怎样?
MySQL 会直接报错,因为 name 列不符合规则:
-
要么把
name加入GROUP BY(但这样分组就变成 "班级+姓名",失去了按班级分组的意义); -
要么用聚合函数处理
name(比如MAX(name)取首字母最大的名字,但通常没有意义)。
正确的 SQL 应该是:
SELECT class, MAX(score) -- 只查分组列和聚合列 FROM student GROUP BY class;
结果:
| class | MAX(score) |
|---|---|
| 一班 | 90 |
| 二班 | 85 |
核心原理
ONLY_FULL_GROUP_BY 强制要求:分组后显示的列,必须是 "确定的"。
-
分组列(
GROUP BY中的列)是确定的(每个组唯一); -
聚合列(如
MAX()/SUM()处理的列)是确定的(每组计算出唯一结果); -
其他列(如例子中的
name)在一个组中可能有多个值,无法确定显示哪一个,因此不允许出现在SELECT中。
总而言之就是在使用分组后不要去取查询那些不确定的字段,这样就能保证查询结果的唯一性和可预测性,避免因随机取值导致的业务逻辑错误。
2238

被折叠的 条评论
为什么被折叠?



