单查询混用LEFT JOIN与INNER JOIN查询课程评分统计结果异常如何解决
问题成因
- 你对
users表使用了INNER JOIN关联逻辑:无评分的课程通过LEFT JOIN关联course_ratings后,所有cr开头的字段值均为NULL,此时INNER JOIN users的关联条件u.user_id = cr.user_id会判定为不成立,直接过滤掉这类无评分的课程行,最终返回结果仅剩下至少有1条评分记录的课程。 - 冗余关联
users表放大了上述问题:course_ratings的user_id是关联users表的非空外键,只要存在course_ratings记录,对应的用户必然存在,不需要额外关联users表也能完成统计。
修正方案
提供两种可直接落地的修正方式,按需选择即可:
方案1:保留users表关联,修改JOIN类型
将INNER JOIN users改为LEFT JOIN users,保证无评分的课程行不会被过滤:
SELECT c.title, COALESCE(AVG(cr.rating), 0) AS avg_rating, COUNT(u.user_id) AS rating_user_count FROM courses c LEFT JOIN course_ratings cr ON c.course_id = cr.course_id LEFT JOIN users u ON u.user_id = cr.user_id GROUP BY c.course_id, c.title;
注意:多数数据库的严格SQL模式要求
GROUP BY子句包含所有SELECT中未使用聚合函数的字段,因此补充了c.title避免执行报错。如果业务允许同一用户对同一课程多次评分,且需要统计去重后的评分用户数,可将COUNT(u.user_id)改为COUNT(DISTINCT u.user_id)。
方案2:移除冗余的users表关联(更推荐)
直接通过course_ratings表的user_id统计即可,减少关联可以提升查询性能:
SELECT c.title, COALESCE(AVG(cr.rating), 0) AS avg_rating, COUNT(cr.user_id) AS rating_user_count FROM courses c LEFT JOIN course_ratings cr ON c.course_id = cr.course_id GROUP BY c.course_id, c.title;
同上,需要去重用户时改用
COUNT(DISTINCT cr.user_id)即可。
内容的提问来源于stack exchange,提问作者Monoxyd
相关产品推荐
相关产品推荐

