《用实例学习SQL》第四篇:嵌套查询

相关表
在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子句中添加条件做进一步的筛选。

相关子查询我将作为一个专题进行深入的讲解!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值