MySQL查询问题:如何筛选仅2015年选课的学生
解决仅筛选2015年选课学生的SQL问题
嘿,我来帮你搞定这个SQL筛选的问题!你的核心需求是找出只在2015年选过课、完全没选过2016年课程的学生,而当前SQL语句之所以会包含跨年度选课的学生,是因为e.subjectCode NOT LIKE '_______16__'是对单条选课记录做过滤——只要学生有一门2015年的课,这条记录就会被选中,哪怕他同时选了2016年的课,最终分组后自然会把他包含进来。
下面给你几个靠谱的解决方案:
方法1:用NOT EXISTS子查询(最直观)
这种方法直接检查学生是否存在2016年的选课记录,同时确保他确实选过2015年的课:
SELECT s.firstName, d.degreeCode FROM students s JOIN degrees d ON s.studentID = d.studentID WHERE NOT EXISTS ( -- 检查该学生是否有2016年的选课记录 SELECT 1 FROM enrolled e WHERE e.studentID = s.studentID AND e.subjectCode LIKE '_______16__' ) AND EXISTS ( -- 确保该学生确实选过2015年的课,避免无选课记录的学生被误选 SELECT 1 FROM enrolled e WHERE e.studentID = s.studentID AND e.subjectCode LIKE '_______15__' ) GROUP BY s.studentID, s.firstName, d.degreeCode;
注:GROUP BY里加上s.studentID是为了避免重名学生被合并,不同数据库对GROUP BY的严格性要求不同,加上主键更稳妥。
方法2:用GROUP BY + HAVING统计选课年份
通过统计学生的选课记录中2016年课程的数量,确保数量为0,同时2015年课程数量大于0:
SELECT s.firstName, d.degreeCode FROM students s JOIN degrees d ON s.studentID = d.studentID JOIN enrolled e ON s.studentID = e.studentID GROUP BY s.studentID, s.firstName, d.degreeCode HAVING -- 2016年选课数为0 SUM(CASE WHEN e.subjectCode LIKE '_______16__' THEN 1 ELSE 0 END) = 0 -- 2015年选课数至少为1 AND SUM(CASE WHEN e.subjectCode LIKE '_______15__' THEN 1 ELSE 0 END) > 0;
方法3:用LEFT JOIN排除法
通过左连接2016年的选课记录,筛选出没有匹配到2016记录的学生:
SELECT DISTINCT s.firstName, d.degreeCode FROM students s JOIN degrees d ON s.studentID = d.studentID JOIN enrolled e1 ON s.studentID = e1.studentID LEFT JOIN enrolled e2 ON s.studentID = e2.studentID AND e2.subjectCode LIKE '_______16__' WHERE e1.subjectCode LIKE '_______15__' -- 没有匹配到2016年的选课记录 AND e2.studentID IS NULL;
注:用DISTINCT是因为一个学生可能有多门2015年的课,避免结果重复。
内容的提问来源于stack exchange,提问作者onenonly
相关产品推荐
相关产品推荐

