在 MySQL 高版本中,默认启用了 sql_mode=ONLY_FULL_GROUP_BY,这是为了确保 SQL 查询在 GROUP BY 子句中的一致性和正确性。该模式要求查询中非聚合的列必须在 GROUP BY 子句中出现,或者通过聚合函数处理,否则会抛出错误:

ERROR 1055 (42000): Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'table_name.column_name' which is not functionally dependent on columns in GROUP BY clause.

解决方法:

有几种方法可以解决与 ONLY_FULL_GROUP_BY 相关的问题。下面详细介绍了几种常见的解决方案。


1. 临时禁用 ONLY_FULL_GROUP_BY 模式

如果你只希望在当前会话中禁用 ONLY_FULL_GROUP_BY,可以使用以下 SQL 命令:

SET SESSION sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));

这个命令只会在当前会话有效。会话结束后,ONLY_FULL_GROUP_BY 将重新启用。

步骤

  1. 登录到 MySQL 数据库。
  2. 执行上述命令来临时禁用 ONLY_FULL_GROUP_BY
  3. 执行你的查询。

2. 永久禁用 ONLY_FULL_GROUP_BY 模式

如果你希望永久禁用 ONLY_FULL_GROUP_BY,需要修改 MySQL 的配置文件并重启 MySQL 服务。

步骤

  1. 修改 MySQL 配置文件(my.cnf 或 my.ini
    • 在 Linux 上,通常配置文件位于 /etc/my.cnf 或 /etc/mysql/my.cnf
    • 在 Windows 上,配置文件通常位于 MySQL 安装目录下的 my.ini
  2. 禁用 ONLY_FULL_GROUP_BY
    在 my.cnf 或 my.ini 中,找到 [mysqld] 部分,并添加或修改如下配置:[mysqld] sql_mode=NO_ENGINE_SUBSTITUTION 这个配置将禁用 ONLY_FULL_GROUP_BY 模式。
  3. 重启 MySQL 服务
    • 对于 Linux 系统,使用以下命令重启 MySQL:sudo service mysql restart # 或者 sudo systemctl restart mysql
    • 对于 Windows 系统,可以通过服务管理工具重启 MySQL 服务,或者使用命令行:net stop mysql net start mysql
  4. 验证是否禁用
    执行以下命令查看当前 SQL 模式,确保 ONLY_FULL_GROUP_BY 不再列出:SELECT @@sql_mode;

3. 修改查询,避免违反 ONLY_FULL_GROUP_BY

如果你不想禁用 ONLY_FULL_GROUP_BY,可以修改查询来符合该模式的要求。 ONLY_FULL_GROUP_BY 要求所有不在 GROUP BY 子句中的列,必须是 函数依赖 的,或者必须使用聚合函数。

解决方法

  1. 使用聚合函数
    确保 GROUP BY 查询中的所有列,要么在 GROUP BY 中,要么通过聚合函数进行处理。原查询:SELECT column1, column2 FROM table_name GROUP BY column1; 修改后查询:SELECT column1, MAX(column2) AS column2 FROM table_name GROUP BY column1; 在此查询中,column2 被包裹在 MAX() 聚合函数中,这样就满足了 ONLY_FULL_GROUP_BY 模式的要求。
  2. 将所有非聚合列添加到 GROUP BY 子句中修改前查询:SELECT column1, column2 FROM table_name GROUP BY column1; 修改后查询:SELECT column1, column2 FROM table_name GROUP BY column1, column2; 这样,你将 column2 添加到 GROUP BY 中,从而避免了错误。
  3. 使用 ANY_VALUE() 函数
    如果你想选择列,但不希望在 GROUP BY 中包含该列,并且不想使用聚合函数,你可以使用 ANY_VALUE()函数,这个函数返回一个任意的值。修改后查询:SELECT column1, ANY_VALUE(column2) FROM table_name GROUP BY column1; 使用 ANY_VALUE() 时,MySQL 会随机选择一个 column2 的值,而不对其进行聚合。

4. 查看和修改当前 SQL 模式

如果你不确定当前是否启用了 ONLY_FULL_GROUP_BY,可以通过以下命令查看当前的 SQL 模式:

SELECT @@sql_mode;

如果返回的结果包含 ONLY_FULL_GROUP_BY,则说明该模式是启用的。

禁用 ONLY_FULL_GROUP_BY(临时)

SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));

注意:使用 SET GLOBAL 命令禁用 ONLY_FULL_GROUP_BY 时,需要 MySQL 的管理员权限。


总结

  • 禁用 ONLY_FULL_GROUP_BY 模式:可以通过配置文件禁用 ONLY_FULL_GROUP_BY,使查询在没有聚合函数的情况下运行。
  • 修改查询:如果不想禁用该模式,可以通过修改查询,使其符合 GROUP BY 的要求,使用聚合函数或将所有相关列添加到 GROUP BY 中。
  • 使用 ANY_VALUE():当你不关心某列的值时,可以使用 ANY_VALUE() 函数来绕过 ONLY_FULL_GROUP_BY 的限制。

根据你的需求选择合适的解决方案。