子查询又被称之为嵌套查询,是将查询出来的结果,交给其他的语句来处理。
子查询可以将查询出的结果交给INSERT/UPDATE/DELETE/SELECT中的任意一个来处理,最常用的还是将查询结果交给SELECT语句来使用。
子查询的类型也有很多种,根据查询结果不同,分为:
子查询的语法格式:
SELECT * FROM 表1 WHERE 字段=(SELECT 字段 FROM 表2)
根据子查询的位置,可以分为WHERE之后、FROM之后、SELECT之后。
例如:
以下演示的几种子查询案例,都是由前面创建的人员信息表和部门信息表来演示。
标子查询返回的结果通常都是单个值,例如数字、字符串、日期等等,返回单个值都称为标量子查询。
很多应用场景了,通过多表联查等等手段最终计算出一个结果,拿到结果之后还需要在根据结果去查询,基于这些场景都会通过子查询来实现。
查询出技术运维部的所有员工信息。
思路:首先查询出技术运维部的部门ID,然后根据部门ID去统计人员表的信息。
1)首先查询出技术运维部的部门ID。
select id from bmxxb where bmmc = '技术运维部';
2)根据部门ID去人员信息表查询出具体的人员。
select * from ryxxb where bm_id = '2';
到此为止其实已经查询出我们想要的数据了,但是不太满意这种操作。
3)下面通过子查询的方式来实现,和第二条SQL类似,只不过将值改成了获取这个值的SQL。
select * from ryxxb where bm_id = (select id from bmxxb where bmmc = '技术运维部');
查询结果如下,查询出了运维部的所有人员信息
查询张子云同事入职之后,新入职的同事。
思路:其实就是查询张子云入职公司以后其他新入职的同事,查询出张子云同事的入职时间,然后只要大于这个入职时间的人员都算是新员工。
1)查询出张子云人员的入职日期。
select rzsj from ryxxb where xm = '张子云';
2)直接使用子查询查询出张子云员工入职之后其他的新入职人员。
select * from ryxxb where rzsj > (select rzsj from ryxxb where xm = '张子云');
子查询返回的结果是一列数据,或者说是由多行的一列数据,这种查询就被称为列子查询。
列子查询返回的结果有多个,通过由特定的操作符来完成数据的查询。
常用的列子查询操作符:IN、NOT IN、ANY、SOME、ALL。
操作符 | 描述 |
---|---|
IN | 在指定的集合范围之内,多选一 |
NOT IN | 在指定的集合范围之内的数据,不选 |
ANY | 子查询返回的列表中,只要有一个满足即可 |
SOME | 与ANY等同 |
ALL | 子查询返回的列表中所有的值都必须满足。 |
查询出技术运维部、平台开发部所有的员工信息。
思路:和前面标量子查询的案例一类似,只不过这里变成了两个部门,首先分别查询出各个部门的ID,然后根据ID查询出所有的人人员。
1)查询出技术运维部、平台研发部的部门ID。
select id from bmxxb where bmmc in ('技术运维部','平台研发部');
2)根据返回的结果通过子查询查询出每个部门的人员信息。
select * from ryxxb where bm_id in (select id from bmxxb where bmmc in ('技术运维部','平台研发部'));
查询结果如下,技术运维部和平台开发部的所有人员信息都被查询了出来。
查询比销售部人员薪资都高的人员信息。
思路:首先查询出销售部每个人员的工资列表,然后去查询大于这些工资的人员信息,注意要求的是比销售部每个人的薪资都高的其他人员信息,因此这里就要用到列子查询的ALL操作符了。
1)获取销售部每个人员的工资。
select xz from ryxxb where bm_id in (select id from bmxxb where bmmc = '销售部');
2)根据返回的多列,使用子查询查询出比这些工资都高的人员信息。
select * from ryxxb where xz > all (select xz from ryxxb where bm_id in (select id from bmxxb where bmmc = '销售部'));
查询结果如下,所有比销售部门人员薪资高的其他人员信息都被查询出来了。
查询比技术运维部中任意一人的工资高的人员信息。
思路:首先查询出技术运维部每个人的工资,然后通过列子查询,使用ANY操作符,只要比其中一个人的工资高的人员信息都需要打印出来。
1)查询出技术运维部所有人的工资。
select xz from ryxxb where bm_id in (select id from bmxxb where bmmc = '技术运维部');
2)根据返回的多列,使用子查询查询出比其中一个工资高的人员信息。
select * from ryxxb where xz > any (select xz from ryxxb where bm_id in (select id from bmxxb where bmmc = '技术运维部'));
查询结果如下,技术运维部有个人的薪资是9000,所有比9000高的人员都被查询了出来。
子查询返回的结果是一行数据,一行多列的形式,这种子查询就被成为行子查询。
行子查询被INSERT语句嵌套的场景也比较常见。
行子查询的操作符:=、<>、IN 、NOT IN
查询出与张亚男的薪资及直属领导都相同的其他人员信息。
思路:首先要查询出张亚男人员的薪资以及直属领导的ID,然后根据这两个字段的值查询出其他人员的信息。
1)首先获取张亚男的薪资以及直属领导的ID。
select xz,zsld_id from ryxxb where xm = '张亚男';
2)根据查询到的两个值,查询出具有相同值的其他人员信息。
select * from ryxxb where xz = '11000' and zsld_id = '2';
数据虽然是被查询出来了,但是这种方式是我们按照一个一个字段去查出来的,显然这条SQL语句不能将获取该值的查询语句嵌套进去,下面还有一种写法可以做到。
格式:SELECT * FROM 表名 WHERE (字段1,字段2) = ('值1','值2')
select * from ryxxb where (xz,zsld_id) = ('11000','2');
3)此时我们就可以将值列表替换成子查询语句了。
select * from ryxxb where (xz,zsld_id) = (select xz,zsld_id from ryxxb where xm = '张亚男');
查询结果如下,通过行子查询,查询出来我们需要的数据。
表子查询返回的结果是多行多列,相当于一张表,这种子查询类型称之为表子查询。
表子查询的应用场景:
表子查询的常用操作符是IN,因为是多行多列的结果,无法使用等于。
查询与牛泽阳、张亚男两位员工职业相同、薪资相同的其他员工信息。
思路:首先查询出牛泽阳和张亚男俩人的职位名称以及薪资的数据,然后通过表子查询嵌套的方式,查出来相同数据的其他员工。
1)首先查询出牛泽阳和张亚男俩人的职位和薪资数据。
select zw,xz from ryxxb where xm in ('牛泽阳','张亚男');
2)根据查询出来的多行,通过表子查询查询出与这两行数据相同的其他数据。
select * from ryxxb where (zw,xz) in (select zw,xz from ryxxb where xm in ('牛泽阳','张亚男'));
查询出入职日期是2019-02-05之后的新入职人员信息,以及部门信息。
思路:首先查询出2019-02-05之后入职的人员信息,通过表子查询的方式嵌套这条SQL语句,将查询结果看做是一张新表,然后与部门表进行左外连接查询。
1)首先查询出2019-02-05之后入职的人员信息。
select * from ryxxb where rzsj > '2019-02-5';
此时就可以把结果集当做是一张新表了。
2)将查询的SQL作为嵌套SQL,放在FROM之后,充当表1,然后把部门表充当表2,通过左外连接的方式查询出人员对应的部门名称。
select ry.*,bm.* from (select * from ryxxb where rzsj > '2019-02-5') as ry left join bmxxb as bm on ry.bm_id = bm.id;
查询结果如下,对应的人员信息以及部门信息都显示了出来。
查询出人员信息表的所有数据,然后写入到员工信息表
思路:通过子查询查询出每一条的记录,然后由INSERT写入新表。
insert into ygxxb (select * from ryxxb);
数据成功写入。