插件窝 干货文章 MySQL 中 GROUP BY 子句的字段要求:在早期版本和 5.7 版本及之后的差异是什么?

MySQL 中 GROUP BY 子句的字段要求:在早期版本和 5.7 版本及之后的差异是什么?

GROUP 子句 版本 模式 308    来源:    2025-04-01

MySQL GROUP BY 子句的字段要求在不同版本中的差异

MySQL 5.7 及以后版本对 GROUP BY 子句的处理与早期版本有显著区别,主要体现在 SQL 模式的严格性上。

早期版本 (5.7 之前)

在 MySQL 5.7 之前的版本中,GROUP BY 子句的行为较为宽松:

  1. 非严格模式:即使 SELECT 列表中的列不在 GROUP BY 子句中,也不是聚合函数的参数,查询也能执行
  2. 隐式选择:MySQL 会从每个分组中任意选择一行作为该列的值
  3. 潜在问题:这种宽松行为可能导致不确定的结果,因为返回的值可能来自分组中的任意行

示例:

-- 在5.7之前可以执行,但name的值不确定
SELECT id, name, COUNT(*) FROM users GROUP BY id;

MySQL 5.7 及以后版本

从 MySQL 5.7 开始,默认启用了 ONLY_FULL_GROUP_BY SQL 模式,对 GROUP BY 有更严格的要求:

  1. 严格模式:SELECT 列表中的每个非聚合列都必须在 GROUP BY 子句中列出
  2. 明确性要求:确保查询结果明确,避免不确定的值
  3. 错误提示:违反规则会报错:"ERROR 1055 (42000): ... isn't in GROUP BY"

示例:

-- 5.7及以后版本会报错,因为name不在GROUP BY中
SELECT id, name, COUNT(*) FROM users GROUP BY id;

-- 正确写法
SELECT id, name, COUNT(*) FROM users GROUP BY id, name;

解决方案

  1. 修改查询:确保所有非聚合列都包含在 GROUP BY 子句中
  2. 使用聚合函数:对非分组列使用聚合函数(如 MAX, MIN, GROUP_CONCAT)
  3. 调整SQL模式(不推荐): sql SET SESSION 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 模式启用,因为它能确保查询结果的确定性和一致性,避免潜在的数据不一致问题。