为了查询已经检修了某两门课程的学生,你可以使用SQL的IN
子句来筛选出这些学生。
一、示例1:
假设有一个表student_courses
,其中包含学生ID和他们选修的课程ID,
学生ID:sid,学生名字:sname,
选修的课程ID:cid,课程名字:cname,
表如下:
查询示例如下:
SELECT DISTINCT sid
FROM student_courses
WHERE cid IN (cid1, cid2)
GROUP BY sid
HAVING COUNT(DISTINCT cid) = 2;
这里cid1
和cid2
是你想要查询的两门课程的ID。COUNT(DISTINCT cid)
保证了只要学生选了这两门课程,不管他选了多少门课程,只要确实选了这两门,就会被选出来。
结果:
确保你的表名和列名与上述示例相对应。如果你的表名或列名不同,请相应地修改查询。
二、示例2:
假如有三张表:学生表,选课表,课程表。
学生表:students。
选课表:choices。
课程表:courses。
问题:请用嵌套查询找出都选修了database和java课程的学生学号和姓名(交运算)。
错误写法:
select sid,sname
from students
where sid in
(select sid
from choices
where cid in
(select cid from courses where cname in ('database','java')));
错误结果:
学号1215选修了database,但是并没有选修java,却也被查询了出来,和我们想要的结果不太一样。
这里查出来的是选修了database和选修了java的学生的并集,并不是交集。
正确写法1:
select sid,sname
from students natural join choices natural join courses
where cname='database'
and sid in
(select sid from choices natural join courses where cname = 'java');
或者
SELECT s.sid, s.sname
FROM student s
JOIN choices t1 ON s.sid = t1.sid AND t1.cid = '10001'
JOIN choices t2 ON s.sid = t2.sid AND t2.cid = '10004'
这个SQL查询语句选取了所有同时选修课程编号为'c002'和'c003'的学生的学生ID和姓名。它通过两次联接takes表,每次联接条件是课程ID分别为'c002'和'c003',并且学生ID需要相同。这样就可以找到同时选修两门课程的学生。
上面的这两种写法虽然能查询正确的数据,但是如果需要查询的选修课程有很多个,这样写很明显会造成sql语句臃肿。
正确写法2:
只查询学号:
select distinct ch.sid from choices ch where ch.cid in
(select cid from courses where cname in ('database','java'))
group by ch.sid
having count(distinct ch.cid)=2;
查询学号和姓名:
select sid,sname
from students
where sid in
( select ch.sid
from choices ch
where ch.cid in
(select cid from courses where cname in ('database','java'))
group by ch.sid
having count(distinct ch.cid)=2);
结果是:
写后语:
当然除了上述sql写法,用关联查询可能会更简单,这里要求用嵌套查询,所以如上写法。