一、带有in谓词的子查询
在嵌套查询中,子查询的结果往往是一个集合,所以谓词in是嵌套查询中最经常使用的谓词。
1、查询与“刘晨”在同一个系学习的学生。
先分步完成此查询,然后再构造嵌套查询。
a.确定“刘晨”所在的系名
select sdept from student where sname='刘晨';
结果为:计算机
b.查找所有在“计算机”系学习的学生
select sno ,sname,sdept from student
where sdept='计算机';
将第一步查询嵌入到第二步查询的条件中,构造嵌套查询如下:
select sno,sname,sdept
from student
where sdept in (
select sdept from student
where sname='刘晨'
);
本例中,子查询的查询条件不依赖于父查询,称为不相关子查询。一种求解方法是由里向外处理,即先执行子查询,子查询的结果用于建立其父查询的查找条件。得到如下的语句:
select sno ,sname,sdept from student
where sdept in('计算机');
然后执行该语句。
本例中的查询可以用自身连接来完成:
select s1.sno ,s1.sname,s1.sdept //解法二
from student s1 ,student s2
where s1.sdept=s2.sdept and
s2.sname='刘晨';
可见,实现同一个查询可以有多种方法,当然不同的方法其执行效率可能会有差别,甚至会差别很大。这就是数据库编程人员应该掌握的数据库性能调优技术。
二、带有比较运算符的子查询
带有比较运算符的子查询是指父查询与子查询用比较运算符进行连接。当用户能确切知道内层查询返回的是单值时,可以用>,<,=,>=,<=,!=或<>等比较运算符。
1、由于一个学生只可能在一个系学习,也就是说内查询的结果是一个值,因此可以用=代替in:
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);
x是表sc的别名,又称为元组变量,可以用来表示sc的一个元组。内层查询是求一个学生所有选修课程平均成绩的,至于是哪个学生平均成绩要看参数x.sno的值,而该值是与父查询相关的,因此这类查询称为相关子查询。
这个语句的一种可能的执行过程是:
1、从外层查询中取出sc的一个元组x,将元组x的sno值(200215121)传送给内层查询。
select avg(grade) from
sc y where y.sno='200215121';
2、执行内层查询,等到值88(近似值),用该值代替内层查询,得到外层查询:
select sno,cno
from sc x
where grade>=88;
3、执行这个查询,得到
(200215121,1)
(200215121,3)
然后外层查询取出下一个元组重复上述1至3步骤的处理,直到外层的sc元组全部处理完毕。结果为
(200215121,1)
(200215121,3)
(200215122,2)
求解相关子查询不能像求解不相关子查询那样,一次将子查询求解出来,然后求解父查询。内层查询由于与外层查询有关,因此必须反复求值。