MySQL 5.7.5+ 默认启用 ONLY_FULL_GROUP_BY 模式,严格校验 GROUP BY 语义,要求 SELECT 中非聚合字段必须出现在 GROUP BY 子句或套用聚合函数,否则报错 ERROR 1055。

为什么GROUP BY突然报错ERROR 1055
MySQL 5.7.5+ 默认启用 ONLY_FULL_GROUP_BY,不是配置错了,是它开始按SQL-92标准校验GROUP BY语义了。以前能跑的 SELECT user_id, name, COUNT(*) FROM orders GROUP BY user_id,现在直接报错——因为 name 既没进 GROUP BY,也没套聚合函数,MySQL无法保证返回哪一行的 name 值。
这不是“修复”,而是明确告诉你:这个字段的值在组内不唯一,你得自己说清要怎么取。
快速确认是不是它在作怪
连上数据库后,先执行这句:
SELECT @@sql_mode;
如果返回值里包含 ONLY_FULL_GROUP_BY(通常在最前面),就是它。注意:@@SESSION.sql_mode 和 @@GLOBAL.sql_mode 可能不同,优先看当前会话的值。
- 云数据库(如阿里云RDS)查不到
@@GLOBAL.sql_mode?正常,权限受限,得去控制台「参数模板」里改 - 本地MySQL用
SET SESSION sql_mode = '...'临时改完,一定要再SELECT @@sql_mode确认——漏掉逗号、多出空格或不可见字符都会让赋值静默失败
三种实操路径,选哪个取决于你控不控制环境
路径一:重写SQL(推荐长期用)
把非聚合字段显式处理掉,最安全:
- 补进
GROUP BY:比如SELECT user_id, name, COUNT(*) FROM orders GROUP BY user_id, name - 套
ANY_VALUE():比如SELECT ANY_VALUE(name), user_id, COUNT(*) FROM orders GROUP BY user_id—— 这等于告诉MySQL:“我知道name有多个值,我接受任意一个” - 用聚合函数:比如
MAX(name)或GROUP_CONCAT(name),视业务需要而定
路径二:临时关掉(仅限调试/CI)
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
当前会话生效,不影响别人:
SET SESSION sql_mode = (SELECT REPLACE(@@sql_mode, 'ONLY_FULL_GROUP_BY,', ''));
⚠️ ORM(如Laravel、Django)或连接池(如HikariCP)可能在每次查询前重置会话变量,导致这句白设。
路径三:永久关掉(慎用)
- 自建MySQL:改
my.cnf的[mysqld]段,加一行sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION,然后重启 - 云数据库:必须走控制台参数模板,删掉
ONLY_FULL_GROUP_BY,保存后「重启实例」——这是服务中断操作,别在高峰期干
ANY_VALUE()比关模式更值得习惯
关掉 ONLY_FULL_GROUP_BY 是掩盖问题;ANY_VALUE() 是声明意图。它不改变结果逻辑,只是把隐式行为显式化。而且从MySQL 5.7.5起就内置支持,无需额外配置。
容易被忽略的一点:如果你的表有主键或唯一索引列,在GROUP BY主键时,其他列其实“功能依赖”于它(比如 GROUP BY id 时选 name 是确定的),MySQL 8.0+ 会自动放行,但5.7不会——所以别指望靠索引绕过,老老实实用 ANY_VALUE() 或补 GROUP BY 最稳。










