假设有这样一个需求:检索出学过001号教师所讲的所有课程的同学。表结构及数据见图。
该需求的语义可以转换为:检索出这样的同学:不存在一门001号教师讲的课程:该同学没学过。
SQL语句:
注意这里有2层子查询
select sno 学号,
name 姓名,
sex 性别,
age 年龄,
dno 学院,
class 班级
from student s
where not exists
(select * from Course c
where c.tno = '001'
and not exists
(select * from SC
where sc.cno = c.cno
and sc.sno = s.sno
)
);
exists是先执行外层查询,然后遍历外层查询的结果集,对结果集的每条记录,判断子查询中有无符合内层查询条件的记录,如果有,就将外层结果集中当前的记录选择到最终的结果集中,反之去掉该条记录。
not exists则相反,如果子查询中有记录,就将外层结果集中当前的记录去掉,反之将该条记录选择到最终的结果集中。
因此很显然,(not)exists的子查询是相关子查询,因为内层查询要有和外层匹配的查询条件,才能进行exists判断。
执行计划如下:
可见入口是对Student的全表扫描,然后才对内层查询进行过滤,最后根据内层查询过滤出的结果,对外层查询进行过滤,并选择出最终的结果集。可见有很多的Filter。