[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 中。

总而言之就是在使用分组后不要去取查询那些不确定的字段,这样就能保证查询结果的唯一性和可预测性,避免因随机取值导致的业务逻辑错误。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐