数据库NOT EXISTS的理解

数据库有查询有四种运算:选择、投影、连接、除运算;而NOT EXISTS关键字则是基于除运算的查询。


例如:

SC表(Sno是学生号,Cno是课程号)

+-----------+-----+-------+
| Sno       | Cno | Grade |
+-----------+-----+-------+
| 201215121 | 1   |    92 |
| 201215121 | 2   |    85 |
| 201215121 | 3   |    88 |
| 201215122 | 2   |    90 |
| 201215122 | 3   |    80 |
+-----------+-----+-------+

Student表

+-----------+--------+------+------+-------+
| Sno       | Sname  | Ssex | Sage | Sdept |
+-----------+--------+------+------+-------+
| 201215121 | 李勇   | 男   |   20 | CS    |
| 201215122 | 刘晨   | 女   |   19 | CS    |
| 201215123 | 王敏   | 女   |   18 | MA    |
| 201215125 | 张立   | 男   |   19 | IS    |
+-----------+--------+------+------+-------+

Course表

+-----+--------------+------+---------+
| Cno | Cname        | Cpno | Ccredit |
+-----+--------------+------+---------+
| 1   | 数据库       | 5    |       4 |
| 2   | 数学         | NULL |       2 |
| 3   | 信息系统     | 1    |       4 |
| 4   | 操作系统     | 6    |       3 |
| 5   | 数据结构     | 7    |       4 |
| 6   | 数据处理     | NULL |       2 |
| 7   | PASCAL语言   | 6    |       4 |
+-----+--------------+------+---------+

一. 查询选修了全部课程的学生的姓名。

此时,查询涉及到三个表。查询方式如下:


select Sname
from Student
where not exists  // (1)没有一门课程他没选的	(对于某个Sname)
         (
		select *
		from Course
		where not exists   // (2)一门课程他没选的。(对于某个Cno)		
                  	(
				select *
				from SC
				where Sno=Student.Sno and Cno=Course.Cno
			)
	);
因为,题目的意思也就是: 没有 一门课程他没有选的

可以将这个句子看成两部分,所以:

最外层查询:

没有 就是代表不存在,也就是说,对于Student,就是为了寻找符合 <没有> 这个条件的Sname;好的,这个语句的一部分工作完成了,接下来写子语句的时候就不再考虑 <没有> 条件。

第一层子查询:

现在开始考虑 <一门课程他没选的> , 也就是说,现在的工作是:子查询试图努力找出一门他没选的课程;即是,对于某个Cno ,不存在 .... (然后开始第二层子查询)。

第二层子查询:

这个时候,又是对第一层查询的否定了,这时候意思是:

对于从第二层查询迭代来的Cno , 看有没有与内层Cno相等的;且,Sno=Student.Sno

Sno=Student.Sno作用:

图.1 Sno=Student.Sno作用



二.查询至少选修了学生201215122选修的全部课程的学生号码。

此时,查询只涉及SC表。

即是:对于符合条件的y,不存在一门课程,201215122选了,而y学生没有选。

select DISTINCT Sno
from SC s1
where not exists          // 不存在
	(
		select *
		from SC s2
		where s2.Sno='201215122' and not exists      // 201215122选了,y学生没有选(对于被20121522选了的Cno)
			(
				select *
				from SC s3
				where s1.Sno=s3.Sno and s3.Cno=s2.Cno
			)
	);

此处的s1.Sno=s3.Sno 的作用和图.1一样。







评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值