子查询(sub query
),查询是建立别的查询结果之上的,也就是一个 select
语句中包含另外一个 select
语句 ;
分类
有两类:按照位置分,按照查询结果分 ;
按照位置分:子查询(select
子语句)在外部查询语句(select
父语句)中出现的位置 ;
From
子查询 :子查询跟在from
之后 ;where
子查询:子查询出现在where
条件中 ;exists
子查询:子查询出现在exists
里面 ;
按照查询结果分:根据查询得到的结果进行分类 ;
-
标量子查询:子查询得到的结果是 一行一列 ;
-
列子查询:子查询得到的结果是 一列多行;
-
行子查询:子查询得到的结果是 一行多列(多行多列);
上面几个出现的位置都是在
where
之后 ; -
表子查询:子查询得到的结果是 多行多列
出现的位置在
from
之后 ;
标量子查询
案列:知道班级名字,查询出该班所有学生 ;
分析:但是学生表中,只有班级 id
,没有班级名字,因此,需要先查出班级 id
,再拿着 id
去查学生 ;
其中查询班级 id
的操作,就是 标量子查询 ,因为它查出来的结果是一行一列 ;
-- 第一步,根据班级id查询学生
select * from student where c_id = ? ;
-- 第二步 ,查询班级 id
select id from class where name = '软件工程2021' ;
-- 合并
select * from student where c_id = (select id from calss where name = '软件工程2021') ;
标量子查询
案列:查询所有在读(名字在班级表中)的学生 ;
分析: 学生表中的有的学生是往届的,我们现在需要查询出在读的 ;
我们需要去查询班级表,拿到所有的班级id
,然后去学生表中,根据id
查询出学生 ;
-- 查询对应的学生
select * from student where c_id in (?) ;
-- 查询所有班级的id
select id from calss ;
-- 拼接在一起
select * from student where c_id in (select id from calss ) ;
使用 in
,顺便提一下 mysql
失败的设计 any
,some
,all
。
any
和 in
的意思一样,都是其中一个的意思, 但是在使用的时候前面需要加上 =
。因为 any
语义不对,没有意思,必须=any
才有 里面的任意一个 的语义;
some
则是失败产物 any
的补救,因为 !=any
语义是一点都不,这和它设计的初衷,不是其中一个,背道而驰了,设计者,才想起来,我曹,any
, 在否定时态中,含义完全相悖,赶紧设计一个 some
来救场 ;(some
完全等价于 any
)
all
则是全部的意思,条件必须全部匹配上,才行。!=all
则是全部不匹配 ;
any
,some
,all
,使用都需要搭配 =
!=
;
行子查询
**案例:查询整个学生中,年龄最大并且身高是最高的
-
朴素的做法:
mysql> select * from student where -> age = (select max(age) from student) -> and -> height = (select max(height) from student);
这里统计函数,不是用在
where
后面,而是用在了标量子查询
里面,因此是可以使用的; -
行子查询:
只有构建
行元素
,才算上是行子查询;mysql> select * from student where -> -- 构建行元素 -> (age,height) -> = (select max(age),max(height) from student);
表子查询
将子查询的结果当做二维表使用;这个有别于前面的几个,返回的结果都不能称为是二维表 ;
案例:找出某个班中身高最高的人;
-- 先让学生表按照身高降序排序
select * from student order by height desc ;
-- 然后按照班级分组
select * from student group by c_id ;
-- 合并在一起,就是我们需要的
select * from (select * from student group by c_id) as student order by height desc ;
我们可以看到,该子查询,发生在 from
之后,将得到的结果作为from
的数据源,所以,表子查询,也称 from
子查询 ;
Exists查询
用来判断条件是否满足,可以理解为 if
;
exists
接在 where
之后使用 ;
exists
的返回值只要 0
1
两种 ;
案例:如果班级表有数据,则查出学生表的数据(好无厘头的需求。。);
select * from student where
-- 判断班级表是否存在
exists(select * from calss) ;