解决MySQL 1055错误:ONLY_FULL_GROUP_BY问题详解(MySQL 8.0版)
当你执行SQL查询时突然遇到"1055 - Expression #1 of SELECT list is not in GROUP BY clause…"错误,是不是一脸懵?别担心!这篇文章将用最简单的语言解释这个MySQL 8.0常见错误的原因和解决方案,即使你是SQL小白也能轻松搞定!
错误重现:典型的报错场景
SELECTproduct_id,product_name,pic,sp_data,SUM(quantity) AS total_sales
FROM order_items
GROUP BY sku_id; -- 这里只按sku_id分组
错误信息:
1055 - Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'ry-mall.item.product_id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
一、错误原因解析(小学生也能懂!)
想象你有一盒彩色铅笔(数据库表),里面有:
- 铅笔型号(sku_id)
- 铅笔颜色(product_name)
- 生产批次(product_id)
- 铅笔图片(pic)
现在老板要求:“按铅笔型号分组,统计每种型号的总数量,同时显示颜色、批次和图片”
问题来了:
- 同一型号可能有不同颜色(比如型号A001有红色和蓝色)
- 分组后,MySQL不知道该显示红色还是蓝色
- 这就是 ONLY_FULL_GROUP_BY 模式的作用 - 防止数据混乱!
📌 核心原因:SELECT中的列(如product_name)没有出现在GROUP BY中,MySQL无法确定取哪个值
二、3种解决方案(附详细示例)
方案1:完善GROUP BY子句(推荐⭐️⭐️⭐️⭐️⭐️)
SELECTproduct_id,product_name,pic,sp_data,SUM(quantity) AS total_sales
FROM order_items
GROUP BY sku_id, -- 原始分组列product_id, -- 新增product_name, -- 新增pic, -- 新增sp_data -- 新增
✅ 优点:
- 完全符合SQL标准
- 数据100%准确
- 适合所有MySQL版本
🚫 缺点:
- GROUP BY列表较长
方案2:使用聚合函数(高效方案⭐️⭐️⭐️⭐️)
SELECTMAX(product_id) AS product_id, -- 使用MAX取值MAX(product_name) AS product_name, -- 使用MAX取值MAX(pic) AS pic,MAX(sp_data) AS sp_data,SUM(quantity) AS total_sales
FROM order_items
GROUP BY sku_id -- 只需分组一列
✅ 适用场景:
- 当同一sku_id对应的其他列值相同时
- 需要优化查询性能时
❗ 重要提示:
- 如果同一sku_id有不同颜色,MAX()会取字母排序最后的颜色(如"蓝色">“红色”)
- 使用前需确认业务逻辑是否允许
方案3:临时关闭严格模式(应急方案⭐️)
-- 第一步:查看当前模式
SELECT @@sql_mode;-- 第二步:移除ONLY_FULL_GROUP_BY
SET SESSION sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';-- 第三步:执行原SQL
SELECT ... (原始问题语句)
⚠️ 强烈不推荐:
- 可能导致数据随机显示
- 每次重连数据库都要重新设置
- 生产环境绝对禁止!
三、原问题SQL修复完整版
SELECTitem.product_id,item.product_name,item.pic,item.sp_data,SUM(item.quantity) AS total_sales -- 去掉IFNULL更简洁
FROM oms_order_item item
INNER JOIN oms_order o ON o.id = item.order_id -- 改用INNER JOIN
WHERE o.STATUS IN (1, 2, 3)AND item.create_time >= '2025-07-28 00:00:00'AND item.create_time < '2025-07-29 00:00:00'
GROUP BY item.sku_id,item.product_id, -- 关键修复!item.product_name, -- 关键修复!item.pic, -- 关键修复!item.sp_data -- 关键修复!
ORDER BY total_sales DESC
LIMIT 10;
四、预防措施 & 最佳实践
-
设计表结构时:
-- 确保sku_id能唯一确定商品信息 ALTER TABLE products ADD UNIQUE (sku_id);
-
永久修改sql_mode(慎重!):
-- 编辑MySQL配置文件 my.cnf: [mysqld] sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
-
开发规范:
- 所有SELECT的非聚合列必须出现在GROUP BY中
- 使用别名时特别注意:
SELECT product_id AS id, -- 别名... GROUP BY product_id -- 必须用原始列名!
总结:选择哪种方案?
情况 | 推荐方案 | 原因 |
---|---|---|
生产环境 | 方案1(完善GROUP BY) | 数据绝对安全 |
测试环境 | 方案2(使用MAX) | 执行更快 |
紧急调试 | 方案3(关闭严格模式) | 快速验证 |
💡 记住这个黄金法则:GROUP BY中的列,应该能唯一确定SELECT中的其他列。遵循这个原则,你将永远告别1055错误!