1、子查询的定义及分类
定义: 子查询(sub query)是指总的查询是在某个结果之上进行的查询,即是一条select语句内部包含了另外一条select语句。
分类的方法: 子查询可以按照两种方式进行分类,分别为按子查询语句在外部查询语句的位置分类、按子查询查询的结果分类;
按照子查询语句的位置分类:
- from子查询:子查询跟在from之后
- where子查询:子查询跟在where之后
- exists子查询:子查询跟在exists之后
按查询结果分类:
- 标量子查询:子查询得到的结果是一行一列
- 列子查询:子查询得到的结果是一列(一列多行)
- 行子查询:子查询得到的结果是一行(一行多列)
注: 以上几个子查询出现的位置在where之后 - 表子查询:子查询得到的结果是多行多列(出现的位置在from之后)
上面就是关于子查询分类及定义的一些介绍,下面将会针对各种子查询进行较为详细的介绍。
2、标量子查询
我们通过一个例子来看标量子查询的语法等信息。
首先,先用下列SQL语句建立相关数据表
//建立班级表
create table if not exists class(
id tinyint primary key auto_increment,
cname varchar(10)
);
//插入数据
insert into class(cname) values('python班'),
('java班'),
('AI班'),
('linux班');
//建立老师表
create table if not exists head_master(
id tinyint primary key auto_increment,
tname varchar(10),
c_id tinyint,
constraint c_id foreign key(c_id) references class(id)
);
//插入数据
insert into head_master(tname,c_id) values('刘天一',1),
('悬空',2),('李志毅',3),('黄华基',4);
然后看下面例子
例:知道班级名字为’python班’,想获取该班的班主任信息
解析:
//确定数据源,该结果的数据源肯定来自于老师表
select * from head_master where c_id = ?;
//确定名字为"python班"的班级id
select id from class where c_name = 'python班';
//综合上述两个语句
select * from head_master where c_id = (select id from class where cname = 'python班');
子查询得到的结果为一列一行:
上述语句执行结果如下:
3、列子查询
同“2”,先看一个例子:
查询班级名称为“python班”、“AI班”、“linux班”的班主任信息
解析:
//先确定数据源(因为是查询班主任信息,所以肯定是要从head_master表中找)
select * from head_master where c_id = ?;
//确定条件(即是确定问号处的内容,也就是要根据班级名称找出班级id,必须要在class表中找)
select id from class where cname in ('python班','AI班','linux班');
//综合上述两个语句,得到最终的查询语句
select * from head_master where c_id in
(select id from class where cname in ('python班','AI班','linux班'));
作为子查询的查询结果(即第二条查询语句的结果):
最终的查询结果如下:
4、行子查询
展示行子查询的例子:查询整个学生中年龄最大并且身高最高的学生
//主查询
select * from student having age = (?) and height = (?);
//确定最大年龄和最大身高
select max(age) from student;
select max(height) from student;
//将上述的三个语句进行合并
select * from student having
age = (select max(age) from student)
and height = (select max(height) from student);
//再对上述语句进行处理,形成真正的行子查询
select * from my_student where (age,height)=(select max(age),max(height) from my_student);
注: 上述语句中(age,height)称为行元素
5、表子查询
定义: 子查询返回的结果是多行多列的二维表,更多的是因为子查询返回的结果是当做二维表来使用的。
实例: 找出每个班中最高的一个学生
//先将总体学生按照身高从高到底的顺序排序
select * from student order by height desc;
//从每个班选出第一个学生
select * from student group by c_id;
--表子查询:from子查询 得到的结果作为from的数据源
//综合上述语句,形成此题解答
select * from (select * from student order by height desc) s group by c_id;
注意! 上述最后的语句绝对不能写成“select * from student group by c_id order by height;”;因为这条语句是先从表中取出数据,然后按照c_id进行分组,并且取每组的第一个数据,最后进行排序,然后进行显示,而不是先将每个班级的排序,再进行分组。
6、exists子查询
exists关键字解析: 是否存在的意思,exists子查询就是用来判断某些条件是否满足,exists子句经常接在where之后,其返回的结果只有0和1;
对于exists关键字返回结果的证明:
//1、
select exists (select * from head_master);
//2、
select exists (select * from head_master where id = 10);
结果1、
结果2、
实例: 只要有班级存在,就查询所有的学生
select * from student where exists (select c_id from class);