代码
SELECT s.student_id, s.student_name, sub.subject_name, COUNT(e.subject_name) AS attended_exams FROM Students s CROSS JOIN Subjects sub LEFT JOIN Examinations e ON s.student_id = e.student_id AND sub.subject_name = e.subject_name GROUP BY s.student_id, s.student_name, sub.subject_name ORDER BY s.student_id, sub.subject_name;🔧 分步解释:
1.CROSS JOIN Students 和 Subjects
- 这一步就是“配对所有学生和所有科目”。
- 比如 Alice + Math、Alice + Physics、Bob + Math……一个不漏。
- ✅ 这样就保证了“即使没考试,也要列出”。
2.LEFT JOIN Examinations
- 把考试记录“贴”到上面的配对上。
- 如果某学生某科有考试记录,就加上;如果没有,那一行的考试信息就是
NULL。 - 用
LEFT JOIN是为了保留左边的所有配对(不会丢掉没考试的组合)。
3.COUNT(e.subject_name)
- 统计每个学生-科目组合实际考了多少次。
- 为什么不是
COUNT(*)?
因为COUNT(*)会把“没考试”的行也数成 1(它数的是“行数”)。
而COUNT(e.subject_name)只数非空值——没考试时e.subject_name是NULL,就不计入,结果就是 0。✅
4.GROUP BY
- 因为我们用了
COUNT()(聚合函数),所以必须按学生+科目分组。 - 否则数据库不知道“到底要统计谁的考试次数”。
5.ORDER BY
- 题目要求按
student_id和subject_name排序,所以加上这句让结果整齐。
结果
解题步骤: