(十五)子查询


子查询(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 失败的设计 anysomeall

anyin 的意思一样,都是其中一个的意思, 但是在使用的时候前面需要加上 = 。因为 any 语义不对,没有意思,必须=any 才有 里面的任意一个 的语义;

some 则是失败产物 any 的补救,因为 !=any 语义是一点都不,这和它设计的初衷,不是其中一个,背道而驰了,设计者,才想起来,我曹,any , 在否定时态中,含义完全相悖,赶紧设计一个 some 来救场 ;(some 完全等价于 any

all 则是全部的意思,条件必须全部匹配上,才行。!=all 则是全部不匹配 ;

anysomeall ,使用都需要搭配 = !=


行子查询

**案例:查询整个学生中,年龄最大并且身高是最高的

  • 朴素的做法:

    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) ;
原文地址:https://www.cnblogs.com/young-youth/p/11665634.html