1.查询选修了全部课程的学生姓名。
SELECT Sname
FROM StudentWHERE NOT EXISTS
(SELECT *
FROM Course
WHERE NOT EXISTS
(SELECT *
FROM SC
WHERE Sno= Student.Sno
AND Cno= Course.Cno);
这道题我看了半天才给看懂了。
说说思路:我们先关注最后这个 select * from sc where sno = student.sno and cno = course.cno ,如果改成:
select * from course,sc where sno = 009 and sc.cno = course.cno ,这句话就很容易看懂了,即查找某个学号为009的学生所选的课。
而在前面加上一个NOT EXISTS,这就是对这句话的否定,
比如:SELECT * FROM Course WHERE NOT EXISTS
(SELECT *FROM SC WHERE sno = 009 AND Cno= Course.Cno),
这就是说,找到009号学生没有选择的课程,其中NOT EXISTS的语义可以这样理解:没有满足某个条件的XXX,XXX是需要select的东西。
弄懂了NOT EXISTS后,我们再回到这道题,其实就是把具体的009号学生换成了student.sno,表示对所有学生遍历判断,而前面的NOT EXISTS还是同样的效果,意思是找到所有没满足某个条件的学生,这个条件是:没有选择某课程,双重否定表示肯定,等同于找到所有选了所有课的学生。
而如果这样写:
SELECT * FROM Course WHERE NOT EXISTS
(SELECT *FROM SC WHERE Cno= Course.Cno),
这句话的语义是什么呢?读者可以先想想。
答案是:找到没有被人选过的课程。
的确是有些绕,关键是要记住NOT EXISTS的语义:找到没有满足某个条件的XXX
2.查询所学课程包含了学生s3所学课程学生的学号:
select distinct sno from sc as x where not exists
(select * from sc as y where y.sno='s3' and not exists
select * from sc as z where z.sno=x.sno and y.cno=z.cno)