in 是一个集合运算符
a in {a,c,d,s,d....}
这个运算中,前面是一个元素,后面是一个集合,集合中的元素类型是和前面的元素一样的.
而exists是一个存在判断
如果后面的查询中有结果,则
则exists为真
否则为假.
in 运算用在语句中,它后面带的select 一定是选一个字段,而不是select *.
比如说你要判断某班是否存在一个名为"小明"的学生,你可以用in 运算:
"小明" in (select sname from student)
这样(select sname from student) 返回的是一个全班姓名的集合,in用于判断"小明"
是否为此集合中的一个数据;
同时,你也可以用exists语句:
exists (select * from student where sname="小明")
select * from 表A where exists(select * from 表B where 表B.id=表A.id)
这句相当于
select * from 表A where id in (select id from 表B)
对于表A的每一条数据,都执行select * from 表B where 表B.id=表A.id的存在
性判断,如果表B中存在表A当前行相同的id,则exists为真,该行显示,否则不显示
区分in和exists主要是造成了驱动顺序的改变(这是性能变化的关键),如果是exists,那么以外层表为驱动表,先被访问,如果是IN,,那么先执行子查询
IN适合于外表大而内表小的情况;EXISTS适合于外表小而内表大的情况
表A
ID NAME
1 A1
2 A2
3 A3
表B
ID AID NAME
1 1 B1
2 2 B2
3 2 B3
表A和表B是1对多的关系 A.ID => B.AID
SELECT ID,NAME FROM A WHERE EXIST (SELECT * FROM B WHERE A.ID=B.AID)
执行结果为
1 A1
2 A2
原因可以按照如下分析
SELECT ID,NAME FROM A WHERE EXISTS (SELECT * FROM B WHERE B.AID=1)
--->SELECT * FROM B WHERE B.AID=1有值返回真所以有数据
SELECT ID,NAME FROM A WHERE EXISTS (SELECT * FROM B WHERE B.AID=2)
--->SELECT * FROM B WHERE B.AID=2有值返回真所以有数据
SELECT ID,NAME FROM A WHERE EXISTS (SELECT * FROM B WHERE B.AID=3)
--->SELECT * FROM B WHERE B.AID=3无值返回真所以没有数据
NOT EXISTS 就是反过来
SELECT ID,NAME FROM A WHERE NOT EXIST (SELECT * FROM B WHERE
A.ID=B.AID)
执行结果为
3 A3
例子 查询选修了全部课程的学生姓名
(? x)P ?? (? x (P)) 查询学生x,不存在课程y,学生没有选修
例 查询选修了全部课程的学生姓名。
用x表示课程,p(x)表示学生学习了课程x,则(? x)p(x)表示对所有课程学生都学习了。
1. 依次取出一个学生,对任何一个课程,查看该学生是否选修了。如果未选修,返回该课
程。
2. 如果选修了,则查看下一个课程。。。。
3. 最终,如果返回的所有课程为空的话说明该学生选修了所有的课程。此时输出该学生的
信息。
例 查询至少选修了学生
查询至少选修了学生查询至少选修了学生
查询至少选修了学生95002选修的全部课程的学生号码
选修的全部课程的学生号码选修的全部课程的学生号码
选修的全部课程的学生号码。
解题思路:
用逻辑蕴函表达:查询学号为x的学生,对所有的课程y,只要95002学生选修了课程y,
则x也选修了y。
形式化表示:
用P表示谓词 “学生95002选修了课程y”
用q表示谓词 “学生x选修了课程y”
则上述查询为: (? ?y) p →q
等价变换:
(? ?y) p →q??(? y (?(p→q)) ??(? y (?(?p∨q) ??(? y (p∧q)
变换后语义:不存在这样的课程y,学生95002选修了y,而学生x没有选。