WITH RankedScores AS (
SELECT
s.student_name,
e.score,
-- 计算排名
ROW_NUMBER() OVER (PARTITION BY c.course_name ORDER BY e.score DESC) AS score_rank,
COUNT(*) OVER (PARTITION BY c.course_name) AS total_students
FROM
students s
JOIN
enrollments e ON s.student_id = e.student_id
JOIN
courses c ON e.course_id = c.course_id
WHERE
c.course_name = '数学'
)
SELECT
student_name,
score
FROM
RankedScores
WHERE
score_rank <= CEIL(total_students * 0.2);
性能优化说明
- 使用窗口函数:通过窗口函数
ROW_NUMBER()
和 COUNT(*)
来计算每个学生在所选课程中的排名以及选修该课程的学生总数,避免了多次扫描表。
- CTE(公用表表达式):使用CTE
RankedScores
提高查询的可读性和可维护性,同时允许在后续的 SELECT
语句中直接引用计算结果。
- 过滤条件前置:在连接表之前,通过
WHERE c.course_name = '数学'
先对 courses
表进行过滤,减少参与连接的数据量,从而提高查询性能。