MySQL中使用SUM()统计时触发ERROR 1111错误的求助
解决MySQL中「Invalid use of group function (ERROR 1111)」错误
首先,咱们来拆解你遇到的问题根源:
错误原因分析
- WHERE子句不能使用聚合函数:你在
WHERE里直接用了SUM()和COUNT(),但WHERE是用来过滤原始行数据的,它不认识分组后的聚合结果。聚合函数的判断应该放在HAVING子句中——HAVING专门用来过滤GROUP BY之后的分组结果。 - 错误的聚合函数嵌套:
SUM(count(distinct ...))是多余的,COUNT(DISTINCT)已经是对每个分组的聚合计算,你不需要再用SUM去包裹它,直接把两个COUNT值相加即可。 - 无效的别名引用:主查询里引用了子查询的
mg别名,这是超出作用域的——子查询的别名只能在子查询内部使用,主查询无法直接访问。
修正后的查询方案
根据你的需求(统计演员3226演过的不同类型数 + 当前演员演过的、且3226没演过的不同类型数 ≥7),我整理了两种可行的查询方式:
方案1:兼容MySQL 5.x及以上版本
先通过子查询获取演员3226的类型数量,再在主查询中计算目标演员的符合条件类型数,最后用HAVING判断总和:
SELECT b.actor_id, -- 获取演员3226演过的不同类型数量 (SELECT COUNT(DISTINCT mg.genre_id) FROM actor a JOIN rolee r ON a.actor_id = r.actor_id JOIN movie m ON r.movie_id = m.movie_id JOIN movie_has_genre mg ON m.movie_id = mg.movie_id WHERE a.actor_id = 3226) AS actor_3226_genre_count, -- 当前演员演过的、3226没演过的不同类型数量 COUNT(DISTINCT bmg.genre_id) AS actor_unique_genre_count FROM actor b JOIN rolee br ON b.actor_id = br.actor_id JOIN movie bm ON br.movie_id = bm.movie_id JOIN movie_has_genre bmg ON bm.movie_id = bmg.movie_id -- 过滤出3226没演过的类型 WHERE bmg.genre_id NOT IN ( SELECT mg.genre_id FROM actor a JOIN rolee r ON a.actor_id = r.actor_id JOIN movie m ON r.movie_id = m.movie_id JOIN movie_has_genre mg ON m.movie_id = mg.movie_id WHERE a.actor_id = 3226 ) GROUP BY b.actor_id -- 在HAVING中判断总和是否≥7 HAVING (actor_3226_genre_count + actor_unique_genre_count) >= 7;
方案2:使用CTE(MySQL 8.0+版本推荐)
用公共表表达式(CTE)提前计算出演员3226的类型数据,避免重复子查询,让代码更清晰:
WITH actor_3226_genres AS ( SELECT COUNT(DISTINCT mg.genre_id) AS genre_count, GROUP_CONCAT(DISTINCT mg.genre_id) AS genre_id_list FROM actor a JOIN rolee r ON a.actor_id = r.actor_id JOIN movie m ON r.movie_id = m.movie_id JOIN movie_has_genre mg ON m.movie_id = mg.movie_id WHERE a.actor_id = 3226 ) SELECT b.actor_id, ag.genre_count + COUNT(DISTINCT bmg.genre_id) AS total_genre_count FROM actor b JOIN rolee br ON b.actor_id = br.actor_id JOIN movie bm ON br.movie_id = bm.movie_id JOIN movie_has_genre bmg ON bm.movie_id = bmg.movie_id CROSS JOIN actor_3226_genres ag -- 过滤3226没演过的类型 WHERE FIND_IN_SET(bmg.genre_id, ag.genre_id_list) = 0 GROUP BY b.actor_id, ag.genre_count HAVING total_genre_count >= 7;
额外优化建议
- 尽量使用
JOIN替代旧的逗号分隔表的写法,让关联逻辑更清晰,也更容易维护。 - 如果
genre_id字段有索引,NOT IN和FIND_IN_SET的性能会更好,建议检查相关表的索引情况。
内容的提问来源于stack exchange,提问作者Salih K. Chousein
相关产品推荐
相关产品推荐

