相关表
在SQL语言中,一个select-from-where语句称为一个查询块,将一个查询块嵌套在另外一个查询块的where或having的条件中的查询称为嵌套查询, 外层的查询称为父查询,内层的查询称为子查询;在sql语句中的嵌套查询的深度是没有限制的,也就是说,可以在子查询中再任意设置子查询。
select Sname
from Student
where Sno in (select Sno from Sc where Cno = '2');
#一个嵌套查询的例子
注意一点:在子查询的语句中不能使用order by语句,它只能在最外层的父查询中使用
子查询分为相关子查询和不相关子查询:
(一)、不相关子查询:
是指子查询的查询条件不依赖于父查询(前面那个例子就是不相关子查询)。
我们再举个例子:
select Sno, Sname
from Student
where Sno in
(select Sno
from Sc
where Cno in
(select Cno
from course
where Cname = '信息系统'
)
);
# 这是由两个嵌套的不相关嵌套查询
这个查询同样可以写成连接查询,达到同样的查询结果
select Student, Sno, Sname
from Student, Sc, Course
where Student.Sno = Sc.Sno and
Sc.Cno = Course.Cno and
Course.Cname = '信息系统';
通过一个三表的连接查询同样达到了查询的目的。
再次重申一下连接查询的思路:先在from语句中从左向右每两个表进行笛卡尔连接,然后对连接的结果(一个组合的table)用where子句中的条件进行元组的筛选
相比于连接运算,关系型数据库对嵌套查询的优化做的还不够完善,所以我们在查询时应该尽量使用连接查询
(二)、相关子查询:
相关子查询当然就是子查询的条件要依赖于父查询(相关子查询有些查询方式可能比较难理解,望细看!)
一个简单的例子:找出每个学生自己选修课程超过其平均成绩的课程号
select Sno, Cno
from Sc x
where Grade >= (select avg(Grade)
from Sc y
where y.Sno = x.Sno);
#这个就是一个相关子查询。
我来讲一下这个查询的步骤:
①从外查询的基本表中取出第一个元组,并将其Sno的值作为参考值放在子查询中
②进行子查询,这一步的子查询是查询出Sc表中所有元组的Sno值与上述参考值相等的元组,然后通过select语句,求出结果元组的成绩的平均值
(那么在第二步中就查询出了学号为Sno的学生的平均成绩)
③最后再次进行外层查询,此时外层查询的条件其实有两个,一个是Sno要是参考值,二个是其Grade大于等于平均成绩。
注意:我们在进行相关子查询时,都要在这时加上一个条件,如上述。
还有一个例子是关于exists关键字的相关子查询。
(exists只关心返回的是不是空集,其实其本身是没有筛选作用的,但是用在相关子查询中就可以对父查询有一定的查询作用)
select Sname
from Student
where exists
(select *
from Sc
where Sno = Student.Sno and Cno = '1');
#一个带有exists的相关子查询
这个查询的步骤和前面一样,但是我还是要讲一下(有区别):
①从外查询中从上向下依次取出一个元组,并将这个元组的Sno值作为参考值放在子查询中
②进行子查询,在子查询中找到Sno与参考值相等的元组,并且该元组的Cno的值必须为‘1’
③只有当满足以上条件时,从外层查询中取出来的元组才具有作为结果元组的资格
select Sname
from Student
where exists
(select *
from Sc
where Sno = Student.Sno);
#更简单的,只要当子查询的基本表中有参考值相等的元组,那么参考值所在的元组就是一个结果元组
更复杂的就是我们可以在父查询的where子句中添加条件做进一步的筛选。
相关子查询我将作为一个专题进行深入的讲解!