学生个人网站设计推广渠道
目录
1.问题发现
2.ONLY_FULL_GROUP_BY模式
2.1. 严格模式 (ONLY_FULL_GROUP_BY 启用,MySQL 5.7.5+ 默认)
2.2 宽松模式 (ONLY_FULL_GROUP_BY 禁用,旧版本默认)
3. 如何避免问题?
方案 1:严格模式 + 正确使用 GROUP BY
方案 2:使用聚合函数明确处理非聚合列
方案 3:临时禁用严格模式(不推荐)
4.总结
1.问题发现
项目使用的mysql数据库,换高版本数据库后发现好多查询sql报错。什么情况,以前不是挺稳定。追踪dao sql查看后发现有很多sql的非聚合列未出现在group by中,这多sql有问题。但是之前好像没有问题,隐约记得mysql查询可以非聚合列不放在group by中。查了资料后原来是mysql8.0默认开启了ONLY_FULL_GROUP_BY模式。
2.ONLY_FULL_GROUP_BY模式
2.1. 严格模式 (ONLY_FULL_GROUP_BY 启用,MySQL 5.7.5+ 默认)
-
会直接报错(错误代码
1055) -
错误信息类似:
ERROR 1055 (42000): Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'db.table.column' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
-
必须将所有非聚合列都包含在
GROUP BY中,或者用聚合函数处理它们。
2.2 宽松模式 (ONLY_FULL_GROUP_BY 禁用,旧版本默认)
MySQL 会从每个分组中任意选择一个值返回,但不保证确定性:
-
可能是该分组的第一条记录的值
-
也可能是最后一条、随机一条,取决于存储引擎和查询执行计划
-
多次执行同一查询可能返回不同的值(数据不稳定)
示例:
假设有一张表 orders:
SELECT customer_id, order_date, -- 不在 GROUP BY 中,且每个 customer_id 有多个 order_dateSUM(amount)
FROM orders
GROUP BY customer_id;
在宽松模式下:
-
对于每个
customer_id,order_date的值是不确定的(可能是该客户最早/最晚/某次订单的日期) -
查询结果不可靠,可能误导业务逻辑。
3. 如何避免问题?
方案 1:严格模式 + 正确使用 GROUP BY
-- 包含所有非聚合列
SELECT customer_id, order_date, SUM(amount)
FROM orders
GROUP BY customer_id, order_date;
方案 2:使用聚合函数明确处理非聚合列
-- 用 MAX/MIN/GROUP_CONCAT 等聚合函数
SELECT customer_id, MAX(order_date) AS latest_order_date,SUM(amount)
FROM orders
GROUP BY customer_id;
方案 3:临时禁用严格模式(不推荐)
SET SESSION sql_mode = ''; -- 关闭 ONLY_FULL_GROUP_BY
4.总结
| 模式 | 行为 | 可靠性 | 建议 |
|---|---|---|---|
| 严格模式 | 直接报错 | 高 | ✅ 推荐,强制写出明确查询 |
| 宽松模式 | 返回任意值 | 低 | ❌ 避免使用,结果不可预测 |
最佳实践:始终启用 ONLY_FULL_GROUP_BY,并确保查询逻辑明确。
