一、在多个表之间进行数据查询,除了可以使用连接查询之外,也可以使用嵌套查询,那么什么是嵌套查询呢?如何使用嵌套查询呢?
1、将一个SELECT-FROM查询,嵌套在另一个SELECT查询语句中,那么这个SELECT-FROM查询就叫嵌套查询或者子查询,被嵌套的上层查询被称为父查询,在子查询中还可以继续嵌入子查询,构成多层嵌套查询,一个查询的结果可能是一个关系,即元组的集合,也可能是一个值,即聚集函数的结果,因此,子查询既可以嵌套在其父查询的SELECT子句的目标列表达式中参与计算,也可以嵌套在其父查询的FROM子句中作为进一步查询的对象,还可以嵌套在其父查询的WHERE子句或HAVING短语的条件表达式中,作为进一步查询的条件,不同的DBMS对嵌套查询的支持程度不同
2、下面介绍几种常用的嵌套查询的使用方式
二、谓词IN实现嵌套查询
IN谓词用于判断一个值是否属于一个集合,其运算结果是一个布尔值
E 【NOT】 IN (V1,V2,...,Vn)
1、将子查询放在IN谓词后面的小括号中,使用子查询查询出来的结果集,实际上还是一个表
2、独立子查询:子查询的结果不依赖于父查询
(1)举例:查询选修了“003”课程的学生姓名
select sN
from s
where sNo in (select sNo from sC where cNo='003')
该查询需求也可以使用连接查询满足,但是从DBMS对SQL语句的查询语句的处理方式来看,嵌套查询语句更有利于生成优化的查询执行方案。
(2)逻辑运算符NOT的使用,举例:查询没有选修“003”课程的学生姓名
select sN
from s
where sNo not in (select sNo from sC where cNo='003')
错误实例:不可以使用连接查询
select sN
from s,sC
where s.sNo=sC.sNo and sC.cNo!='003'
原因:嫦娥不仅选修了003的课程,还选修了其它的课程
三、比较操作符实现嵌套查询
当嵌套查询的结果是一个值是,该嵌套查询可以嵌套在WHERE子句的元组条件选择表达式中
1、举例1:查询选修“003”课程的成绩高于刘备的学生的学号和成绩
use XSXK;
select sNo,grade
from sC
where cNo='003' and grade>(
select grade
from sC
where cNo='003' and sNo in(
select sNo
from s
where sN='刘备'
)
)
这是一个多层嵌套查询,并且每一个子查询都是一个独立子查询
2、举例2:查询每个学生所修课程成绩超过其所有选课平均成绩的学号和课程号
use XSXK;
select sC1.sNo,sC1.cNo
from sC sC1
where grade>(
select avg(sC2.grade)
from sC sC2
where sC2.sNo=sC1.sNo
)
(1)这里的子查询结果与父查询的当前元组有关,这种查询被称为相关子查询
(2)在相关子查询中,如果涉及到了父查询所用到的表,往往要对这两个表至少一个进行重命名操作,以便标识不同的元组
四、使用量词ANY或ALL实现嵌套查询
1、在有些DBMS中,如果子查询的结果是一个集合,还可以使用ANY或ALL与比较符配合来实现嵌套查询
2、ANY(子查询)
ANY的语义为查询结果中的某个值,当子查询结果中有某一个值满足比较运算符,比较运算结果则为真
3、ALL(子查询)
ALL的语义为查询结果中的所有值,当子查询结果中的每一个值都满足比较运算符,比较运算结果才为真。
4、举例1:查询其它院系中比数计学院某个学生年龄小的学生
select *
from s
where sD!='数计学院' and sB > any(
select sB
from s
where sD='数计学院'
)
5、举例2:查询其它院系中比数计学院学生年龄都小的学生
select *
from s
where sD!='数计学院' and sB > all(
select sB
from s
where sD='数计学院'
)
6、量词ANY或ALL与比较运算符配合的功能也可以用谓词IN或用聚集函数与与比较符配合来实现
(1)当子查询的结果是一个集合而不是一个值时,比较运算符前的值肯定会不等于查询结果中的某个值,那么比较运算符不能于ANY结果永真,作为父查询的条件没有意义
(2)举例1:查询其它院系中比数计学院某个学生年龄小的学生
select *
from s
where sD!='数计学院' and sB > (
select min(sB)
from s
where sD='数计学院'
)
(3)举例2:查询其它院系中比数计学院学生年龄都小的学生
select *
from s
where sD!='数计学院' and sB > (
select max(sB)
from s
where sD='数计学院'
)