MySQL 5.6正常运行的SQL在5.7报错,请求改写适配5.7版本
解决MySQL 5.7中GROUP BY导致的SQL执行错误
这个问题我太熟悉了!你遇到的是MySQL 5.7默认启用ONLY_FULL_GROUP_BY SQL模式带来的兼容性问题——这个模式严格遵循SQL标准,要求SELECT列表里的所有非聚合列必须出现在GROUP BY子句中,而MySQL 5.6默认没开启这个模式,所以你的老SQL在5.7里就触发错误了。
你的原SQL本质是想为每个photoable_id保留一条优先级最高的记录(因为子查询里按priority升序排序了),下面给你几种规范的改写方案,按推荐程度排序:
方案1:使用窗口函数(推荐,最符合SQL标准)
用ROW_NUMBER()窗口函数给每个photoable_id分组内的记录编号,按priority升序排列后取每组的第一条,完美匹配你的需求:
SELECT * FROM ( SELECT photos.*, ROW_NUMBER() OVER (PARTITION BY photoable_id ORDER BY priority ASC) AS rn FROM photos WHERE photoable_type = 'Mobilehome' AND photoable_id IN (SELECT id FROM mobilehomes WHERE community_id = 1) AND image_file_size IS NOT NULL AND is_published IS TRUE ) AS tmp_table WHERE rn = 1;
这个写法逻辑清晰,既满足MySQL 5.7的语法要求,也能保证结果的确定性,后续升级到更高版本的MySQL也不会有兼容性问题。
方案2:关联子查询匹配最小优先级记录
如果你的环境有特殊限制(虽然MySQL 5.7已经支持窗口函数了),可以先分组找到每个photoable_id的最小priority,再关联回原表拿到对应记录:
SELECT p.* FROM photos p JOIN ( SELECT photoable_id, MIN(priority) AS min_priority FROM photos WHERE photoable_type = 'Mobilehome' AND photoable_id IN (SELECT id FROM mobilehomes WHERE community_id = 1) AND image_file_size IS NOT NULL AND is_published IS TRUE GROUP BY photoable_id ) AS p_min ON p.photoable_id = p_min.photoable_id AND p.priority = p_min.min_priority WHERE p.photoable_type = 'Mobilehome' AND p.image_file_size IS NOT NULL AND p.is_published IS TRUE;
这种写法也符合ONLY_FULL_GROUP_BY的要求,只是代码量稍大一点。
方案3:临时关闭ONLY_FULL_GROUP_BY(不推荐)
如果你只是临时需要兼容老代码,不想改SQL,可以临时关闭这个模式,但这是权宜之计,不建议长期使用(会导致分组结果不可预期,不符合SQL标准):
-- 临时关闭ONLY_FULL_GROUP_BY SET sql_mode = (SELECT REPLACE(@@sql_mode, 'ONLY_FULL_GROUP_BY', '')); -- 执行你的原SQL SELECT * FROM (SELECT * FROM photos WHERE photoable_type = 'Mobilehome' AND photoable_id IN (SELECT id FROM mobilehomes WHERE mobilehomes.community_id = 1) AND photos.image_file_size IS NOT NULL AND photos.is_published IS TRUE ORDER BY photos.priority ASC) AS tmp_table GROUP BY photoable_id;
内容的提问来源于stack exchange,提问作者Bloomberg
相关产品推荐
相关产品推荐

