如何高效查询含特定学生的课程及该课程所有学生列表?
高效实现筛选含特定学生的课程并列出所有学生
原查询的问题出在WHERE子句的过滤时机:s.name = 'Alice'会在JOIN之后直接过滤掉所有非Alice的学生记录,导致最终聚合时只能拿到Alice的名字,丢失了同课程的其他学生。
更高效简洁的实现方式:用EXISTS筛选课程+一次关联聚合
可以通过EXISTS子句先锁定包含目标学生(Alice)的课程,再关联学生表获取该课程的所有学生进行聚合,只需要一次关联操作,比两次JOIN的效率更高:
SELECT c.name, GROUP_CONCAT(s.name SEPARATOR ',') AS student_list FROM Courses c JOIN Students s ON s.CourseID = c.ID WHERE EXISTS ( SELECT 1 FROM Students s2 WHERE s2.CourseID = c.ID AND s2.name = 'Alice' ) GROUP BY c.ID, c.name
原理说明
EXISTS是半连接查询:它只会检查课程是否存在Alice的记录,找到匹配项后立即停止,不需要返回所有匹配行,执行效率比子查询返回所有ID再用IN的方式更高。- 主查询的
JOIN Students会获取该课程下的所有学生记录,后续的GROUP_CONCAT就能完整聚合所有学生名字,不会丢失数据。
另一种等价写法:用IN子句筛选课程ID
如果习惯用IN子句,也可以先查询出Alice所在的课程ID,再关联聚合,效率和EXISTS接近:
SELECT c.name, GROUP_CONCAT(s.name SEPARATOR ',') AS student_list FROM Courses c JOIN Students s ON s.CourseID = c.ID WHERE c.ID IN ( SELECT CourseID FROM Students WHERE name = 'Alice' ) GROUP BY c.ID, c.name
为什么比两次JOIN高效
两次JOIN的写法通常是先关联筛选课程,再再次关联学生表,本质上是两次全表关联;而上面的方法只做一次学生表关联,筛选课程的操作是轻量的半连接/子查询,避免了重复关联带来的性能开销。
内容的提问来源于stack exchange,提问作者Cave Johnson
相关产品推荐
相关产品推荐

