-
基础表格
student学生表
course课程表
SC选课表
-
问题:选择出选修了所有课程的学生
-
查询语句:
select *
from student s
where not exists
(select *
from course c
where not exists
(select *
from sc
where sc.sno=s.sno and sc.cno=c.cno)
)
-
在navicat上面执行的结果:
-
关于not exists的返回值问题:
exists返回的是对一个结果集是否空的判断,当where里面返回的结果集为空的就false,否则只要存在一个不为空就是true。
not exists,当where里面返回的结果集为空的话就true,否则只要有一个不为空就false。 -
查询语句执行过程的理解:
首先在student表里面选择第一条记录的sno,然后进入course表里面找第一条记录的cno,把sno、cno同时送到最内层子循环的SC表中,按从第一条记录开始匹配,若匹配成功这个结果集就有了一条记录,匹配完SC表,若有一条是匹配成功的,这个子查询里面的not exists返回的就是false,表示sno学生选修了cno这门课,若一条都未匹配,则返回true, 表示sno学生没有选修cno这门课。遍历完SC表后,继续返回course表,选择course表的第二条记录的cno,把sno,cno再次进入最内层子查询,匹配整个SC表格,返回结果也如上。
遍历完SC表,继续返回course表,选择第三条记录的cno,再次把sno,cno再次进入最内层子查询,匹配整个SC表格,返回结果也如上。
这样一直下去,直到整个course表遍历完成。若最内层返回的结果集全部为false,则外面这个not exists返回的是true,则表示这个学生选修了全部的课程,否则只要内层返回的结果集中有一个true,则外面的not exists返回的是false,则表示这个学生未选修全部的课程。
以上是第一个学生的匹配过程。
course表遍历完后,就返回到student表选择第二条记录的sno,进入course表找course表第一条记录的cno,把sno、cno送入最内层子查询中,与SC表中的sno、cno从第一条开始进行匹配······重复上述的步骤。
直到所有student表记录都遍历完成。