SQL查询:筛选至少1门/2门课获A的CS专业学生
针对两个SQL需求的解决方案
你的原语句会返回所有匹配的成绩单记录——如果一个学生有多门课程拿A,会重复出现多条相同的学生信息,而且没法直接满足“至少X门A”的统计需求,以下是针对两个需求的正确写法:
需求1:筛选专业为CS且至少有1门课程成绩为A的学生
写法1:用DISTINCT去重
SELECT DISTINCT s.* FROM student s INNER JOIN transcript t ON s.ssn = t.ssn WHERE s.major = 'CS' AND t.grade = 'A';
通过DISTINCT关键字,把关联后重复的学生记录去重,最终每个符合条件的学生只返回一次。
写法2:用EXISTS子查询(推荐,数据量大时效率更高)
SELECT s.* FROM student s WHERE s.major = 'CS' AND EXISTS ( SELECT 1 FROM transcript t WHERE t.ssn = s.ssn AND t.grade = 'A' );
EXISTS仅检查当前学生是否存在至少一条符合条件的成绩单记录,一旦找到就返回该学生,不会产生重复行,执行效率通常比关联后去重更高。
需求2:筛选专业为CS且至少有2门课程成绩为A的学生
写法1:子查询统计A的数量
SELECT s.* FROM student s INNER JOIN ( SELECT ssn, COUNT(*) AS a_count FROM transcript WHERE grade = 'A' GROUP BY ssn HAVING COUNT(*) >= 2 ) t ON s.ssn = t.ssn WHERE s.major = 'CS';
先在子查询中统计每个学生拿到A的课程总数,筛选出数量≥2的学生SSN,再和student表关联,获取这些学生的完整信息并限定专业为CS。
写法2:关联后分组筛选
SELECT s.* FROM student s INNER JOIN transcript t ON s.ssn = t.ssn WHERE s.major = 'CS' AND t.grade = 'A' GROUP BY s.ssn, s.name, s.major HAVING COUNT(*) >= 2;
先关联两张表并筛选出CS专业且成绩为A的记录,再按学生的所有字段分组,统计每组的记录数(即该学生拿A的课程数),最后保留数量≥2的分组。注意:不同数据库对GROUP BY的要求不同,部分数据库(如开启ONLY_FULL_GROUP_BY的MySQL)要求GROUP BY必须包含所有非聚合的字段。
内容的提问来源于stack exchange,提问作者vamsi shankar
相关产品推荐
相关产品推荐

