SQL——相关子查询和不相关子查询

SQL 专栏收录该内容
1 篇文章 0 订阅

SQL——相关子查询和不相关子查询

在SQL中经常使用在“FROM/WHERE”字句中包含一个形如“SELECT-FROM-WHERE”的查询块,这样的查询块称为子查询嵌套查询,包含子查询的语句称为父查询外部查询

子查询分为相关子查询不相关子查询

接下来将举例说明相关子查询和不相关子查询的原理以及区别

这里有三张表:
学生表student(姓名,学号,性别,年龄,系别)
教师表teacher(姓名,工号,性别,年龄,婚否)
选课表course(课程名,课号,学号,任课教师编号,成绩)

先来看看不相关子查询:

不相关子查询

子查询可独立执行,不依赖于父查询表的查询,称为不相关子查询。
执行过程:
(1)先执行子查询,其结果不会被显示,而是返回给外部查询来作为外部查询的查询条件;
(2)根据子查询的结果,执行外部查询。

例:查询年龄小于所有学生平均年龄的学生

SELECT *
FROM student
WHERE 年龄 < ( SELECT AVG(年龄)
			   FROM student
			   )

本例中只用到了一个表student,先执行子查询,计算出所有学生的平均年龄,再将该平均年龄作为外部查询的查询条件,进而查询出比所有学生平均年龄小的学生的信息。

再举一个例子:查询“刘小晖”老师所授课程的平均成绩

SELECT 课程名,AVG(成绩) AS 平均成绩
FROM course
WHERE 任课教师编号 = 
(		SELECT 工号
		FROM teacher
		WHERE 姓名 = "刘小晖" )
GROUP BY 课号

从以上例子可以看出,在不相关子查询中,子查询在整个查询过程中仅执行了一次,且独立于外部查询。
若单独选中子查询的语句块来执行,也可以得出结果,这说明子查询的确独立于外部查询。

相关子查询

构造子查询的查询条件时需要用到父查询的某一个属性列,这样的查询称为相关子查询。

相关子查询是无法独立执行的,因为它必然含有对外部查询表中元组分量的引用。
其执行过程为:
(1)按顺序从外部查询中取出一个元组,将元组的相关分量值传递给子查询;
(2)执行子查询,得到结果值;
(3)外部查询根据子查询返回的结果或结果集确定取出的这一行元组是否满足条件;若外层的where子句返回真值,说明符合;否则不符合,舍弃。
(4)重复步骤1-3,直到外部查询表中的所有元组都被处理完毕。

最常见的相关子查询是EXISTS引导的子查询。
EXISTS 引导的子查询不返回数据,而是返回是否存在满足子查询的外层查询元组的判断(真/假),主查询根据该判断来逐条取舍元组。

例:查询至少有一门课不及格的学生姓名

SELECT 姓名 FROM student
WHERE EXISTS
(	SELECT * FROM course
 	WHERE course.学号 = student.学号
 		AND 成绩 < 60
)

本例中,执行子查询时,先从外部查询中取出一个元组,也就是从student表中取出一个元组(学生信息),并得到该学生学号作为子查询的查询条件。若该学生存在有至少一门课程不及格,则该学生满足条件,exists返回为真,外层查询保留该元组;否则舍弃。
本例同样可以使用连接查询来实现,而且貌似使用连接查询来实现会更简单;接下来再看一个例子,就能体会到相关子查询的方便之处。

查询所有课程都及格了的学生:

SELECT 姓名 FROM student
WHERE NOT EXISTS
  (SELECT * FROM course
   WHERE course.学号 = student.学号
     AND course.成绩 < 60) 

查询所有课程都及格了的学生,其实就是该学生不存在有不及格的课程。
此例若用连接查询来实现,必然相当繁琐,显然用相关子查询是最简便的。

总结
(1)不相关子查询总是独立于外部查询,整个过程中子查询只执行一次。
(2)相关子查询依赖于外部查询表,其子查询执行的次数等于外部查询表中元组的个数。

  • 4
    点赞
  • 0
    评论
  • 36
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 1024 设计师:白松林 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值