这是由于MySQL启用了ONLY_FULL_GROUP_BY
模式导致的。以下是禁用该模式的三种方法,结合你的需求选择最合适的方案:
一、临时禁用(重启后失效)
1. 当前会话禁用
直接在SQL客户端执行以下命令,仅对当前数据库连接有效:
SET SESSION sql_mode = (SELECT REPLACE(@@sql_mode, 'ONLY_FULL_GROUP_BY', ''));
2. 全局禁用
修改全局设置,对所有新连接生效(但重启MySQL服务后失效):
SET GLOBAL sql_mode = (SELECT REPLACE(@@GLOBAL.sql_mode, 'ONLY_FULL_GROUP_BY', ''));
二、永久禁用(需修改配置文件)
步骤:
-
找到MySQL配置文件:
- Windows:
my.ini
(通常位于MySQL安装目录或C:\ProgramData\MySQL\MySQL Server 8.0
)。 - Linux:
/etc/my.cnf
或/etc/mysql/mysql.conf.d/mysqld.cnf
。
- Windows:
-
修改配置: 在
[mysqld]
部分添加或修改sql_mode
,移除ONLY_FULL_GROUP_BY
。 示例配置:[mysqld] sql_mode = STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
-
重启MySQL服务:
- Windows:通过服务管理器重启MySQL服务。
- Linux:执行
sudo systemctl restart mysql
。
-
验证:
SELECT @@GLOBAL.sql_mode;
确认输出中不再包含
ONLY_FULL_GROUP_BY
。
三、查询优化(推荐)
如果不想修改数据库配置,可以通过以下方式调整SQL语句,使其符合ONLY_FULL_GROUP_BY
规则:
1. 确保所有非聚合列在GROUP BY
中
修改你的SQL,将SELECT
列表中的非聚合列(如network_type
)添加到GROUP BY
子句:
GROUP BY t.id, cdn.cdn_device_network.network_type
2. 使用聚合函数包裹非聚合列
对不需要分组的列使用ANY_VALUE()
函数:
SELECT ANY_VALUE(network_type) AS network_type, ... FROM ... GROUP BY t.id
四、注意事项
- 数据一致性风险:禁用
ONLY_FULL_GROUP_BY
可能导致查询结果不确定,建议生产环境谨慎操作。 - 配置文件优先级:确保修改的配置文件是MySQL实际加载的(可能存在多个配置文件,优先级以最后加载的为准) 。
- MySQL版本差异:MySQL 8.0默认启用此模式,需通过配置文件永久修改 。
总结
- 快速修复:临时禁用(方法一)适合紧急调试。
- 长期方案:修改配置文件(方法二)确保重启后生效。
- 最佳实践:优化SQL查询(方法三),避免依赖数据库模式