PostgreSQL一对多关联表中,如何按课程组合查询对应学生ID
问题描述
现有PostgreSQL数据库中的三张关联表,结构如下:
Students表
| id | Name |
|---|---|
| 1 | Shibbir |
| 2 | Ahmed |
| 3 | John |
Courses表
| id | Name |
|---|---|
| 1 | Data Structure |
| 2 | Algorithms |
| 3 | Math |
student_course_mapping(学生-课程映射表)
| studentId | courseId |
|---|---|
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 2 | 2 |
| 2 | 3 |
| 3 | 1 |
| 3 | 2 |
已知每个学生的选课组合都是唯一的,现在需要写一条SQL语句,输入指定的课程ID列表,找出恰好只选了这些课程的学生ID。比如:
- 输入课程ID
1,2,3,返回学生ID1 - 输入课程ID
2,3,返回学生ID2 - 输入课程ID
1,2,返回学生ID3
解决方案
这里可以用分组统计加条件过滤的方式实现,核心就是要同时满足两个要求:一是学生选的所有课程都在目标列表里,二是学生选的课程数量和目标列表的数量完全一致。
针对固定课程ID的查询示例
比如要找选了1,2,3的学生:
SELECT studentId FROM student_course_mapping GROUP BY studentId HAVING -- 确保该学生的每门课都在目标课程里 EVERY(courseId IN (1, 2, 3)) -- 确保选课数量和目标课程数一致 AND COUNT(DISTINCT courseId) = 3;
支持动态传入课程ID的通用写法
如果需要动态传入课程列表,用PostgreSQL的数组类型会更灵活:
-- 示例:传入课程ID数组 '{1,2}' SELECT studentId FROM student_course_mapping GROUP BY studentId HAVING EVERY(courseId = ANY('{1,2}'::int[])) AND COUNT(DISTINCT courseId) = array_length('{1,2}'::int[], 1);
逻辑说明
GROUP BY studentId:按学生分组,把每个学生的所有选课记录聚合到一起EVERY(...):这个函数会检查分组内的所有行是否都满足条件,这里用来确保学生没有选目标列表之外的课程COUNT(DISTINCT courseId) = N:统计学生的选课数量,和目标课程的数量对比,确保没有少选课程
题目里已经说明每个学生的选课组合唯一,所以最终只会返回符合条件的那一个学生ID。
内容的提问来源于stack exchange,提问作者Shibbir Ahmed
相关产品推荐
相关产品推荐

