(本章查询所用到的表都在博客中的单表查询中,这里直接用表名就不写表的内容了;)
在SQL语言中,一个select - from - where 语句称之为一个查询块。将一个查询块嵌套在另一个查询块的where子句或having短语的条件中的查询称为嵌套查询
例如:
select sname
from student /*外层查询或父查询*/
where sno in
( select sno
from sc /*内层查询或子查询*/
where cno = '2'
);
注意:一个子查询中还允许嵌套其他子查询。但是值得注意的是子查询的select语句中不能使用order by 子句,order by 子句只能对最终的查询结果排序
1.带有IN谓词的子查询
在嵌套查询中,子查询的结果往往是一个集合,所以谓词IN是嵌套查询中最经常使用的谓词
例1、 查询与“刘晨”在一个系学习的学生
select *
from student
where sdept in
(select sdept
from student
where sname = '刘晨')
and sname != '刘晨'
它等价于上篇博客所说的连接查询
select *
from student a,student b
where a.sname = '刘晨' and a.sdept = b.sdept and b.sname != '刘晨'
例2、 查询选修了课程名为“信息系统”的学生学号和姓名。
select sno,sname
from student
where sno in
(select sno
from sc
where cno in
(select cno
from course
where cname = '信息系统'
)
)
//本例题也可以用连接查询做出来,这里就不写了
注意:有些嵌套查询可以用连接运算符代替,有些不能代替,从以上两个例题中可以看出子查询的查询条件不依赖父查询,这类子查询称为不相关子查询。不相关子查询是比较简单的一类子查询。如果子查询的查询条件依赖于父查询,这类子查询称为相关子查询,整个查询语句称为相关嵌套查询。如例3就是一个相关子查询
2.带有比较运算符的子查询
带有比较运算符的子查询是指父查询与子查询之间用比较运算符连接。当用户确切知道内层查询返回的是单值时,可以用<, <=, =, >, >=, !=(或者<>)等比较运算符。
例3、 查询与“刘晨”在一个系学习的学生
select *
from student
where sdept in(或者用=)
(select sdept
from student
where sname = '刘晨')
and sname !='刘晨'
解释:由于一个学生只可能在一个系学习,也就是说内查询的结果是一个值,因此可以用 ’ = ’ 代替 ’ in’
例4、 找出一个学生超过他选修课程平均成绩的课程号
select sno,cno
from sc x
where grade>=
(select avg(grade)
from sc y
where y.sno = x.sno
)
带有any或者all谓词的子查询
子查询返回单值时可以用比较运算符,但是返回多值时要用any或者all谓词修饰;而使用any或all谓词时必须同时使用比较运算符
比较运算符+谓词 | 含义 |
---|---|
>any | 大于子查询结果中的某个值 |
>all | 大于子查询结果中的所有值 |
<any | 小于子查询结果中的某个值 |
<all | 小于子查询结果中的所有值 |
>=any | 大于等于子查询结果中的某个值 |
>=all | 大于等于子查询结果中的所有值 |
<=any | 小于等于子查询结果中的某个值 |
<=all | 小于等于子查询结果中的所有值 |
=any | 等于子查询结果中的某个值 |
=all | 等于子查询结果中的所有值(通常没实际意义) |
!=(或者<>) any | 不等于子查询结果中的某个值 |
!=(或者<>) all | 不等于子查询结果中的任何一个值 |
例5、 查询其他系中比计算机科学系(cs)某个学生年龄小的学生姓名和年龄;
select sname,sage
from student
where sage < any
(select sage
from studet
where sdept = 'cs')
and sdept != 'cs'
等价于
select sname,sage
from student
where sage <
(select max(sage)
from studet
where sdept = 'cs')
and sdept != 'cs'
解释:由上事例可以看出 < any 等价于 <子查询中的最大值, <all 等价于 <子查询中的最小值;同理 > any 等价于 >子查询中的最小值, >all 等价于 >子查询中的最大值;
带有exists谓词的子查询
exists代表存在量词。带有exists谓词的子查询不返回任何数据,只产生逻辑真值“true”或者逻辑假值“false”.
- 若内层查询结果非空,则外层的where子句返回真值
- 若内层查询结果为空,则外层的where子句返回假值
由于exists引出的子查询,其目标列表达式通常都用*,因为带exists的子查询只返回真值或假值,给出列名无实际意义。
例6、 查询未参加选修的学生信息
select *
from student
where not exists
(select *
from sc
where sc.sno = student.sno
)
等价于
select *
from student
where sno not in
(select sno
from sc
)
例7、 查询没有选修1号课程的学生姓名
select sname
from student
where not exists
(select *
from sc
where sno = student.sno and cno= '1'
)
等价于
select sname
from student
where sno not in
(select sno
from sc
where cno = '1'
)