MySQL查询在MySQL5.7/MariaDB正常,MySQL8.0报错如何解决?
问题根因
MySQL 8.0 默认开启ONLY_FULL_GROUP_BYSQL 模式,要求 SELECT 子句中的列要么出现在 GROUP BY 子句中,要么被聚合函数包裹,否则会触发 1055 错误。你之前使用的 MariaDB 10.4 对 GROUP BY 的校验规则更宽松,才会出现本地运行正常、生产环境报错的差异。
不建议关闭ONLY_FULL_GROUP_BY,关闭后数据库会随机返回分组内的任意一行数据,逻辑完全不可控,这也是你关闭模式后应用更早崩溃的原因。
你的原 SQL 实际逻辑是获取每个活跃用户发布的最新1条用户故事,最终取最新的4条结果,按照以下两种方案改写即可在 MySQL 8.0 中正常运行:
方案1:使用窗口函数(MySQL 8.0 原生支持,逻辑最清晰)
SELECT user_id, title, description, posted, expire, thumbnail, id FROM ( SELECT user_id, title, description, posted, expire, thumbnail, id, ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY id DESC) AS rn FROM Wo_UserStory WHERE (user_id IN (SELECT following_id FROM Wo_Followers WHERE follower_id = '1') OR user_id = 1) AND user_id IN (SELECT user_id FROM Wo_Users WHERE active = '1') ) t WHERE rn = 1 ORDER BY id DESC LIMIT 4
ROW_NUMBER()会给每个用户的故事按ID倒序编号,取编号为1的记录就是每个用户最新发布的内容,和原SQL逻辑完全一致。
方案2:先取每个用户的最大ID再关联原表(改动最小的兼容写法)
如果不想大改原SQL结构,可以先拿到每个用户的最大故事ID,再关联回原表获取其他字段:
SELECT w.user_id, w.title, w.description, w.posted, w.expire, w.thumbnail, w.id FROM Wo_UserStory w INNER JOIN ( SELECT user_id, MAX(id) AS max_id FROM Wo_UserStory GROUP BY user_id ) t ON w.user_id = t.user_id AND w.id = t.max_id WHERE (w.user_id IN (SELECT following_id FROM Wo_Followers WHERE follower_id = '1') OR w.user_id = 1) AND w.user_id IN (SELECT user_id FROM Wo_Users WHERE active = '1') ORDER BY w.id DESC LIMIT 4
两种方案都完全符合 MySQL 8.0 的SQL模式要求,不需要调整应用其他代码,运行逻辑和原SQL完全一致。
内容的提问来源于stack exchange,提问作者user16779236
相关产品推荐
相关产品推荐

