SQL练习5-SELECT(嵌套查询EXISTS、集合查询、基于派生表的查询)

带有EXISTS谓词的子查询

EXISTS代表存在量词 ∃ \exists
带有EXISTS谓词的子查询不返回任何数据,只产生逻辑真值“true”或逻辑假值“false”。
使用存在量词EXISTS后,若内层查询结果非空,则外层的WHERE子句返回真值,否则返回假值。
与EXISTS谓词相对应的是NOT EXISTS谓词,使用存在量词NOT EXISTS后,若内层查询结果为空,则外层的WHERE子句返回真值,否则返回假值。

【例3.60】查询所有选修了1号课程的学生姓名。
本查询涉及Student表和SC表,可以在Student表中依次取每个元组的Sno值,用此值去检查SC表。若SC表中存在这样的元组,其Sno值等于Student.Sno值,并且其Cno=‘1’,则取此Student.Sname送入结果表。

SELECT Sname
FROM Student
WHERE EXISTS
   (SELECT *
   FROM SC
   WHERE Sno=Student.Sno AND Cno='1');

由EXISTS引出的子查询,其目标列表达式通常都用 *,因为带EXISTS的子查询只返回真值或假值,给出列名无实际意义。
子查询的查询条件依赖于外层父查询的某个属性值(Student.Sno),因此是相关子查询。处理过程是:首先取外层查询中的Student表的第一个元组,根据它与内层查询相关的属性值(Sno值)处理内层查询,若WHERE子句返回值为真,则取外层查询中该元组的Sname放入结果表;然后取Student表的下一个元组;重复这一过程,直至外层Student表全部检查完为止。
本例查询也可以用连接运算来实现

SELECT Sname
FROM Student,SC
WHERE SC.Sno=Student.Sno AND Cno='1';

【例3.61】查询没有选修1号课程的学生姓名。
与上一题相比就是在EXISTS前面加了一个NOT。

SELECT Sname
FROM Student
WHERE NOT EXISTS
   (SELECT *
   FROM SC
   WHERE Sno=Student.Sno AND Cno='1');

一些带EXISTS或NOT EXISTS谓词的子查询不能被其它形式的子查询等价替换,但所有带IN谓词、比较运算符、ANY和ALL谓词的子查询都能用带EXISTS谓词的子查询等价替换。
【例3.55】查询与“刘晨”在同一个系学习的学生。可以用带EXISTS谓词的子查询替换

/*第四种解法*/
  SELECT Sno,Sname,Sdept
  FROM Student S1
  WHERE EXISTS
   (SELECT *
   FROM Student S2
   WHERE S1.Sdept=S2.Sdept AND S2.Sname='刘晨');

在S1表取一个学生,让这个人的系别与刘晨的系别比较,相同就为真返回这个学生的学号姓名系别,然后取下一个;不为真就直接取下一个;直至表取完。
由于带EXISTS量词的相关子查询只关心内层查询是否有返回值,并不需要查具体值,因此其效率并不一定低于不相关子查询,有时是高效的方法。

用EXISTS/NOT EXISTS实现全称量词 难点
SQL语句中没有全称量词 ∀ \forall ,可以把带有全称量词的谓词转换为等价的带有存在量词的谓词: ( ∀ x ) P ≡ ¬ ( ∃ x ( ¬ P ) ) (\forall x)P \equiv \neg (\exists x(\neg P)) (x)P¬(x(¬P)

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值