如何优化查询选课数≥3学生的带GROUP BY的SQL语句
你的SQL逻辑有偏差,附高效实现方案
首先得明确:你当前写的SQL实际是筛选**选了“至少有3个学生修读的课程”的学生,和你需求的“自己选课数量≥3”**完全不是一回事,逻辑上搞错了。
正确且高效的实现方式
方式一:分组统计关联(通用兼容所有SQL数据库)
SELECT s.firstName, s.Surname FROM students s INNER JOIN ( -- 先统计每个学生的选课数量,筛选出≥3的记录 SELECT student_id FROM course_student GROUP BY student_id HAVING COUNT(*) >= 3 ) cs ON s.id = cs.student_id;
方式二:窗口函数(适合MySQL 8+、PostgreSQL等支持窗口函数的数据库)
SELECT DISTINCT s.firstName, s.Surname FROM students s INNER JOIN ( -- 给每条选课记录标记所属学生的总选课数 SELECT student_id, COUNT(*) OVER (PARTITION BY student_id) AS course_count FROM course_student ) cs ON s.id = cs.student_id WHERE cs.course_count >= 3;
为什么这些写法更高效?
你的原SQL需要两次扫描course_student表(一次子查询按课程分组,一次主查询关联),还做了不必要的IN子查询过滤,逻辑错误的同时性能冗余。
上面两种写法都只需要扫描course_student一次,先完成核心的“统计每个学生选课数”逻辑,再关联学生表获取姓名,步骤简洁,数据库优化器更容易生成高效执行计划。
性能优化建议
给course_student表建立(student_id, course_id)的复合索引,或者至少单独给student_id建索引——分组/窗口统计的核心是按student_id聚合,索引能避免全表扫描,大幅提升统计速度。
内容的提问来源于stack exchange,提问作者Petr Kostroun
相关产品推荐
相关产品推荐

