SQL查询教授学生最多的教师:语法修复与写法优化
问题修复方案
1. 语法错误根因
你遇到的语法错误非常明确:查询最后一行WHERE teacher_student_rank = 1:末尾错误使用了英文冒号:,SQL语句结束需要使用英文分号;,替换该符号后即可正常运行。你单独运行CTE部分没有报错,就是因为CTE段本身语法无问题,错误出在整个查询的收尾位置。
2. 现有写法合理性说明
你当前使用RANK() OVER (ORDER BY 学生数 DESC)的逻辑完全正确:
- 不需要额外加
PARTITION BY子句,该子句的作用是划分排名分区(比如按学期、按院系分组统计组内排名),你的需求是统计全量教师中带教学生最多的人员,属于全局排名,不需要分区。 - 你使用
COUNT(DISTINCT sc.student_id)的考虑很到位,可以避免同一个学生选了同一位老师多门课程时被重复计数,统计结果准确。 RANK()函数会自动处理并列第一的场景:如果有多位老师带教学生数同为最高,会被全部返回,符合通用统计需求。
3. 更简洁的写法参考
如果使用Oracle 12c及以上版本,可以省略CTE,直接用FETCH FIRST WITH TIES实现同等效果,不需要手动编写排名判断逻辑,代码更简洁:
SELECT t.teacher_id , t.first_name , t.last_name , COUNT(DISTINCT sc.student_id) AS teacher_student_count FROM teachers t LEFT JOIN courses c ON t.teacher_id = c.teacher_id LEFT JOIN student_courses sc ON c.course_id = sc.course_id GROUP BY t.teacher_id, t.first_name, t.last_name ORDER BY teacher_student_count DESC FETCH FIRST 1 ROWS WITH TIES;
该写法和你原有RANK写法返回结果完全一致,遇到并列第一的情况会自动返回所有符合条件的教师。
修正后可直接运行的原查询代码
仅修改最后一行的结束符号即可:
WITH teacher_student_rankings AS ( SELECT t.teacher_id , t.first_name , t.last_name , COUNT(DISTINCT sc.student_id) AS teacher_student_count , RANK() OVER (ORDER BY COUNT(DISTINCT sc.student_id) DESC) AS teacher_student_rank FROM teachers t LEFT JOIN courses c ON t.teacher_id = c.teacher_id LEFT JOIN student_courses sc ON c.course_id = sc.course_id GROUP BY t.teacher_id , t.first_name , t.last_name ) SELECT teacher_id , first_name , last_name FROM teacher_student_rankings WHERE teacher_student_rank = 1;
额外优化建议
你提供的测试用例建表语句没有明确指定字段数据类型,虽然Oracle支持从SELECT结果自动推导类型,但生产环境使用时建议明确字段类型,避免隐式类型转换带来的性能问题或逻辑错误,示例:
CREATE TABLE teachers( teacher_id NUMBER PRIMARY KEY, first_name VARCHAR2(50) NOT NULL, last_name VARCHAR2(50) NOT NULL );
内容的提问来源于stack exchange,提问作者Pugzly
相关产品推荐
相关产品推荐

