select Sname from Student
where not exists
(select * from Course
where not exists
(select * from SC
where
Sno=Student.Sno
and
Cno=Course.Cno));
学习sql的时候碰到这货,有点难理解,问度娘找谷哥,终于明白...记录如下:
一、表的结构和数据如下:
Student:
Course:
SC:
二、SQL语句执行过程:
1、sql 结构分析
主查询:select Sname from Student;
嵌套 主查询:select * from Course...
嵌套 子查询:select * from SC where Sno=Student.Sno and Cno=Student.Cno;
关键字:not exists
2、执行过程:
注意:下表中以主键代表该条记录
步骤 | 主查询 记录 | 嵌套 主查询 记录 | 嵌套 子查询 | 嵌套主查询结果集 | 主查询的结果记录 |
1 | 200215121 | 1 | 无匹配记录 | 结果集为空 | 200215121 |
2 | 200215121 | 2 | 无匹配记录 | 200215121 | |
3 | 200215121 | 3 | 无匹配记录 | 200215121 | |
4 | 200215121 | 4 | 无匹配记录 | 200215121 | |
5 | 200215121 | 5 | 无匹配记录 | 200215121 | |
6 | 200215121 | 6 | 无匹配记录 | 200215121 | |
7 | 200215121 | 7 | 无匹配记录 | 200215121 | |
8 | 200215122 | 1 | 有匹配记录 | 结果集非空 | null |
9 | ... | ... | ... | ... | |
10 | 200215122 | 7 | 有匹配记录 | null | |
11 | 200215123 | 1 | 有匹配记录 | 结果集非空 | null |
12 | ... | ... | ... | ... | ... |
13 | 200215123 | 7 | 有匹配记录 | 结果集非空 | null |
14 | 200215125 | 1 | 有匹配记录 | 结果集非空 | null |
15 | ... | ... | ... | ... | ... |
16 | 200215125 | 7 | 有匹配记录 | 结果集非空 | null |
由上图可知该查询语句的返回结果是:
附文字说明:
首先,将主查询的记录和嵌套 主查询的记录查出
然后,取主查询中的第一条记录,依次遍历嵌套 主查询的记录,替换嵌套子查询中的查询条件为Sno=‘200215121’ and Cno=k,(k=1,2,3,4,5,6,7);
取主查询中的第二条记录,依次遍历嵌套查询中的记录,替换嵌套子查询中的查询条件为Sno='200215122' and Cno=k,(k=1,2,3,4,5,6,7);
最后,记录嵌套 主查询为空的主查询记录,将这些记录构成一个结果集即为此查询语句的结果集。
三、总结
1、作为where 查询条件时,exists(结果集为空返回false,否则返回true)
not exists(结果集为空返回true,否则返回false)
2、相关子查询,用主查询的相关属性去替换子查询中的条件从而匹配主结果集
3、题目情景出自某教科书