订阅更新

学生参加各科考试的次数:先做全组合再计数

SQL 实战 123 题 · 第 87 题 简单 约 2 分钟读完

LeetCode 1280 · CROSS JOIN 补全组合、LEFT JOIN 计数

本文目录
  1. 面试怎么回答
  2. 题意
  3. 表结构
  4. 思路
  5. 参考解法
  6. 易错点

面试怎么回答

Students CROSS JOIN Subjects 得到全部组合,再 LEFT JOIN Examinations,按学生和科目分组 COUNT(e.subject_name)。先用笛卡尔积补全维度组合、再左关联事实,是做「补零报表」的标准方法。

先把这段讲顺;面试官追问时,再展开下面的原理和细节。

详细讲解

题意

学生表、科目表、考试记录表。输出每个学生在每门科目上参加考试的次数,没考过的科目也要输出 0。按学生 ID、科目名排序。

表结构

  • Students:student_id(主键)、student_name
  • Subjects:subject_name(主键)
  • Examinations:student_id、subject_name;可能有重复行

思路

结果要覆盖「每个学生 × 每门科目」的所有组合,这些组合在考试表里不一定都有,所以先用 CROSS JOIN 构造完整组合,再 LEFT JOIN 考试记录,按组合分组用 COUNT(考试表的列) 计数,没有考试的组合计为 0。

参考解法

SELECT a.student_id, a.student_name, b.subject_name, COUNT(e.subject_name) AS attended_exams
FROM Students a CROSS JOIN Subjects b
LEFT JOIN Examinations e ON a.student_id = e.student_id AND b.subject_name = e.subject_name
GROUP BY a.student_id, b.subject_name
ORDER BY a.student_id, b.subject_name

易错点

  • 直接从考试表分组,没考过的科目不会出现。
  • 用 COUNT(*) 会把没有考试的组合计成 1。
刷题进度保存在当前浏览器