嵌套查询

119 阅读5分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第5天

嵌套查询讲解

嵌套查询的分类: 1、不相关子查询  2、相关子查询

一、不相关子查询

1、子查询的查询条件不依赖于父查询

2、是由里向外逐层处理。即每个子查询在上一级查询处理之前求解,子查询的结果用于建立其父查询的查找条件。

 

例1、查询学生表与“古月”是老乡的全部同学的信息

两步完成:第一步查古月的籍贯  第二步 查所有这个籍贯的学生

将第一步查询嵌入道第二步查询中

确切知道内层查询返回单值时,可用比较运算符(> = < >= <= !=<>)

select * from dbo.学生1

where 籍贯=(select 籍贯 from dbo.学生1 where 姓名='古月')

 

例2、查询学习了课程号为“002”学生的姓名(两种方法)

注意:有些嵌套查询可以用连接查询实现的

注意:=1个 ,  in多个

select 姓名

from 学生1

where 学号 in (select 学号  from 成绩1 where 课程号 ='002')

 

例3、查询选修了课程名为“数据库技术”的学生的学号和姓名(两种方法)

select  学号,姓名

from 学生1

where 学号 in

(select 学号  from 成绩1 where 课程号 in (select 课程号 from 课程1 where 课程名='高等数学') )

order by 学号 image.png

二、相关子查询:

1、子查询的查询条件依赖于父查询

2、①首先取外层查询中表的第一条记录,根据它,与内层查询相关的属性值处理内层查询,若where子句返回值为真,则取此记录放入结果表中。

②然后再取外层表的下一条记录。

③重复这一过程,直至外层表全部检查完为止。

 

例4、根据成绩表,查询出每个学生超过所有课程平均分的学号、课程号、成绩(不相关子查询) 

select  *

from 成绩1

where 成绩>(select avg(成绩)  from 成绩1)

select avg(成绩)  from 成绩1  平均成绩70

image.png 例5、根据成绩表,查询出每个学生超过本人所有课程平均分的学号、课程号、成绩(相关子查询)

select  *

from 成绩1 a

where 成绩>(select avg(成绩)  from 成绩1 b where a.学号=b.学号)

image.png 嵌套查询的谓词

1、比较运算符的子查询

2、in谓词的子查询

3、any(some) 或all谓词的子查询:any任意一个值,all所有值 需要配合运算符使用

4、exists或not exists谓词的子查询

exists谓词:存在 (不关心结果,只关心存在不存在)—相关子查询

①带有exists的子查询不返回任何数据,只产生逻辑真或逻辑假

l 若内层查询结果非空,则外层的where子句返回真值

l 若内层查询结果为空,则外层的where子句返回假值

②由exists引出的子查询,其目标列表达式通常都用“*”,应为返回真假,给出列名无实际意义

not exists谓词:

若内层查询结果非空,则外层的where子句返回假值

若内层查询结果为空,则外层的where子句返回真值

 

例6、查询学生表里,比高考成绩平均分高的学生的学号、姓名和高考成绩

select  学号,姓名,高考成绩

from 学生1

where 高考成绩>(select avg(高考成绩) from 学生1)

image.png 例7、查询学生表里,比吉林省长春市高考成绩都要高的学生的学号、姓名、高考成绩

 

select  学号,姓名,高考成绩,籍贯

from 学生1

where 高考成绩>all(select 高考成绩 from 学生1 where 籍贯='吉林省长春市')

image.png 比吉林省长春市所有的都高  ,大于最高值(605)

 

select  学号,姓名,高考成绩,籍贯

from 学生1

where 高考成绩<all(select 高考成绩 from 学生1 where 籍贯='吉林省长春市')

image.png 比吉林省长春市所有的都低  ,小于最低值(415)

 

select  学号,姓名,高考成绩,籍贯

from 学生1

where 高考成绩>any(select 高考成绩 from 学生1 where 籍贯='吉林省长春市')

大于最低值

image.png select  学号,姓名,高考成绩,籍贯

from 学生1

where 高考成绩<any(select 高考成绩 from 学生1 where 籍贯='吉林省长春市')

小于最低值

image.png select  学号,姓名,高考成绩,籍贯

from 学生1

where 高考成绩<any(select 高考成绩 from 学生1 where 籍贯='吉林省长春市')

and 籍贯!='吉林省长春市' (注意这是夫查询块中的条件)

image.png 例8、查询学习了003号课程的学生姓名(三种方法实现)

select  姓名

from 学生1

where exists

(select  *  from 成绩1 where 课程号='003')  

写什么课程号结果都是8个人,因为这个子查询结果永远为真

 

select  姓名

from 学生1

where exists

(select * from 成绩1 where 课程号='003' and  学号=学生1.学号)

image.png select  姓名

from 学生1

where 学号 in

(select 学号 from 成绩1 where 课程号='003' )

 

select  姓名

from 学生1 join 成绩1  on  学生1.学号=成绩1.学号

where 课程号='003'

 

例9、查询没有学习003号课程的学生姓名(几种方法实现)

select  姓名

from 学生1

where not exists

(select * from 成绩1 where 课程号='003' and  学号=学生1.学号)

image.png select  姓名

from 学生1

where 学号 not in

(select 学号 from 成绩1 where 课程号='003' )

总结:不同形式的查询间的替换

一些带 exists或not exists的子查询不能被其他形式的子查询等价替换

所有带in谓词、比较运算符、any和all谓词的子查询都能用带exists谓词的子查询等价替换。