查询选修了全部课程的学生姓名
1. SELECT
2. Sname
3. FROM S
5. WHERE NOT EXISTS (
6. SELECT * FROM course WHERE NOT EXISTS (
7. SELECT * FROM SC WHERE Sno = student.Sno AND Cno = course.Cno ) );
WHERE后面的 NOT EXISTS()表示条件判断,当括号内没有符合条件的元组时,返回TRUE,否则返回FALSE.
然后我们根据题意进行逻辑转换:
学生 选择 全部课程 = 学生 不存在 没有选的课
SELECT Sname FROM S WHERE NOT EXISTS (没有选的课 )
没有选的课=课 不存在 已经被选
SELECT * FROM course WHERE NOT EXISTS ( 已经被选 )
已经被选的课
SELECT * FROM SC WHERE Sno = student.Sno AND Cno = course.Cno
这就是大体的思路,但是我们要想一下为什么要这样做?
首先我想先说明一下EXISTS()和 NOT EXISTS() 。我们知道 WHERE 后面的式子表示条件判断,当返回的值为 TRUE 时,才进行前面的选择,当返回的值为 FALSE 时,则不进行选择。
EXIEST()表示当括号里存在元组时,返回TRUE。(有一项存在即可)
NOT EXISTS()表示当括号里不存子元组时,返回TRUE。(必须是全部,没有一项存在)
我们现在开始从头往后捋,我们要选择学生姓名,期待后面的条件是TRUE,而我们的条件是选修全部课程,所以用 NOT EXISTS()比较合适。然后我们再次选择没有被选的课,期待后面的条件是TRUE,我们很容易想到用EXISTS()来找到其中一个学生与课程不对应的就行,但是我们SC表中存储的是学生对应的选课关系,没有被选的课需要用到否定来转换,既可以用NOT EXISTS()来表示。
我们可能又有疑问了,不是要根据全部或其中之一这个条件来选择吗?
我们应当注意,在第一个选择时是一对多,而在第二次选择时,已经代入了上一层的学生,进行的是一对一的选择,此时NOT EXISTS()和EXISTS()表示一样。