嵌套查询
不相关子查询:子查询的查询条件不依赖于父查询
由里向外逐层处理。即每个子查询在上一级查询处理之前求解,子查询的结果用于建立其父查询的查找条件。
相关子查询:子查询的查询条件依赖于父查询
- 首先取外层查询中表的第一个元组,根据它与内层查询相关的属性值处理内层查询,若Where子句返回值为真,则取此元组放入结果表。
- 然后再取外层表的下一个元组。
- 重复这一过程,直至外层表全部检查完成为止。
1.带有IN谓词的子查询
例1:查询与“刘晨”在同一个系学习的学生。
①确定“刘晨”所在的系名
select sdept from student where sname = '刘晨';
result: CS
②查找所有在CS系学习的学生。
select sno,sname,sdept from student where sdept='CS';
将它们写成一个嵌套查询
select sno,sname,sdept from student where sdept in
(select sdept from student where sname = '刘晨');
此查询为不相关子查询
也可以用自连接来完成。
2.带有比较运算符的子查询
当能确切知道内层查询返回单值时,可用比较运算符(>,<,=,>=,<=,!=或者<>)
在例1中当我们知道一个学生只能在一个系学习时,可用
select sno,sname,sdept from student where
sdept = (select sdept from student where sname = '刘晨');
例2:找出每个学生超过他选修课程平均成绩的课程号
select sno,cno from sc x where
grade>=(select avg(grade) from sc y where y.sno=x.sno)
上面这个查询为相关子查询,需要用到父查询的数据。
执行顺序为:
可以近似的理解为两层for循环,父查询为外层for循环,子查询为内层for循环,从父查询中取出一个元组的x,将元组x的sno值传送给内查询进行处理比较。然后重复此过程,最终得到结果。
3.带有ANY(SOME)或ALL谓词的子查询
- 引入ANY和ALL谓词,其对象为某个查询结果,表示其中任意一个值或者全部值
- 引入EXIST谓词,其对象也是某个查询结果,但表示这个查询结果是否为空,返回真值。
使用ANY和ALL谓词时必须同时使用比较运算符
语义为:
>ANY 大于子查询结果中的某个值
>ALL 大于子查询结果中的所有值
<ANY 小于子查询结果中的某个值
>ALL 小于子查询结果中的所有值
>=ANY 大于等于子查询结果中的某个值
>=ALL 大于等于子查询结果中的全部值
例3:查询非计算机科学系中比计算机科学系任意一个学生年龄小的学生姓名和年龄
select sname,sage from student where
sage<any(select sage from student where sdept='CS') and sdept <>'CS'
4.带有EXISTS谓词的子查询
- 带有EXISTS谓词的子查询不返回任何数据,只产生逻辑真值“true”或者逻辑假值“false”。
- 若内层查询结果非空,则外层的where子句返回真值。
- 若内层查询结果为空,则外层的where子句返回假值。
- 由EXISTS引出的子查询,其目标列表达式通常都用*,因为带有EXISTS的子查询只返回真值或假值,给出列名无实际意义。
例4:查询所有选修了1号课程的学生姓名
分析: - 在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')