52人参与 • 2026-09-29 • Mysql
子查询(subquery),也叫嵌套查询,是 mysql 中在一个查询语句内部嵌套另一个查询的高级语法,能实现复杂的多表关联、条件过滤、数据筛选,是 sql 进阶的核心知识点。
本文围绕图片中的 5 大类子查询,从语法、逻辑、代码示例三个维度,带你彻底掌握 mysql 子查询。
select/insert/update/delete 语句中的 select 语句,也叫「内查询」创建两张关联表,用于所有示例:
create table student (
stu_id int primary key auto_increment,
stu_name varchar(20) not null,
class varchar(10) not null,
age int not null
);
insert into student values
(1, '张三', '一班', 18),
(2, '李四', '二班', 19),
(3, '王五', '一班', 18),
(4, '赵六', '三班', 20),
(5, '孙七', '二班', 19);create table score (
score_id int primary key auto_increment,
stu_id int not null,
subject varchar(20) not null,
score int not null,
foreign key (stu_id) references student(stu_id)
);
insert into score values
(1, 1, '语文', 85),
(2, 1, '数学', 92),
(3, 2, '语文', 78),
(4, 2, '数学', 88),
(5, 3, '数学', 88),
(6, 4, '英语', 60),
(7, 5, '语文', 95);用 = > < >= <= != 等比较运算符,将外层查询的字段与子查询返回的单行单列结果进行比较。
要求:子查询必须返回1 行 1 列的标量值,否则报错。
-- 需求:查询成绩 > 班级平均分的学生信息
-- 步骤1:先查二班的平均分(子查询,返回标量)
-- 步骤2:外层查询筛选成绩 > 平均分的学生
select s.stu_name, sc.subject, sc.score
from student s
join score sc on s.stu_id = sc.stu_id
where s.class = '二班'
and sc.score > (
-- 子查询:计算二班的平均分
select avg(score) from score
where stu_id in (select stu_id from student where class = '二班')
);| stu_name | subject | score |
|---|---|---|
| 李四 | 数学 | 88 |
| 孙七 | 语文 | 95 |
子查询先算出二班平均分 (78+88+95)/3 ≈ 87,外层查询筛选出二班中成绩 > 87 的学生。
in 用于判断外层字段是否在子查询返回的多行单列结果集中,等价于「多个 or 条件」。
要求:子查询返回多行 1 列的结果集。
-- 需求:查询有成绩的学生信息(子查询返回所有有成绩的stu_id)
select * from student
where stu_id in (
-- 子查询:返回所有有成绩的stu_id(多行单列)
select distinct stu_id from score
);
-- 反向:查询没有成绩的学生(not in)
select * from student
where stu_id not in (select distinct stu_id from score);| stu_id | stu_name | class | age |
|---|---|---|---|
| 1 | 张三 | 一班 | 18 |
| 2 | 李四 | 二班 | 19 |
| 3 | 王五 | 一班 | 18 |
| 4 | 赵六 | 三班 | 20 |
| 5 | 孙七 | 二班 | 19 |
子查询先查出所有有成绩的 stu_id,外层查询用 in 匹配学生表,筛选出对应学生。
any 和 some 完全等价,表示 **「满足子查询结果中的任意一个」**,即「只要有一个满足条件,就返回 true」。
语法:
字段 > any(子查询)→ 字段 > 子查询结果中的任意一个值(等价于 > 最小值)语法:字段 < any(子查询)→ 字段 < 子查询结果中的任意一个值(等价于 < 最大值)
-- 需求:查询成绩 > 一班任意学生成绩的学生(即 > 一班最低分)
select s.stu_name, sc.subject, sc.score
from student s
join score sc on s.stu_id = sc.stu_id
where sc.score > any(
-- 子查询:一班所有学生的成绩(85,92,88)
select sc2.score from score sc2
join student s2 on sc2.stu_id = s2.stu_id
where s2.class = '一班'
);| stu_name | subject | score |
|---|---|---|
| 张三 | 数学 | 92 |
| 李四 | 数学 | 88 |
| 王五 | 数学 | 88 |
| 孙七 | 语文 | 95 |
一班成绩为 [85,92,88],> any 等价于 > 85(最小值),因此所有 >85 的成绩都会被筛选出来。
all 表示 **「满足子查询结果中的所有值」**,即「必须全部满足条件,才返回 true」。
语法:
字段 > all(子查询)→ 字段 > 子查询结果中的所有值(等价于 > 最大值)语法:字段 < all(子查询)→ 字段 < 子查询结果中的所有值(等价于 < 最小值)
-- 需求:查询成绩 > 一班所有学生成绩的学生(即 > 一班最高分)
select s.stu_name, sc.subject, sc.score
from student s
join score sc on s.stu_id = sc.stu_id
where sc.score > all(
-- 子查询:一班所有学生的成绩(85,92,88)
select sc2.score from score sc2
join student s2 on sc2.stu_id = s2.stu_id
where s2.class = '一班'
);| stu_name | subject | score |
|---|---|---|
| 孙七 | 语文 | 95 |
一班最高分为 92,> all 等价于 > 92,因此只有孙七的 95 分满足条件。
exists 是关联子查询,子查询会引用外层查询的字段,执行逻辑为:
exists 为 true,外层行保留;否则丢弃特点:子查询不返回实际数据,只返回
true/false,性能极高(适合大表)
-- 需求:查询有成绩的学生信息(exists 版本,等价于 in 版本)
select * from student s
where exists(
-- 关联子查询:用外层s的stu_id查询成绩表
select 1 from score sc
where sc.stu_id = s.stu_id
);
-- 反向:查询没有成绩的学生(not exists)
select * from student s
where not exists(
select 1 from score sc
where sc.stu_id = s.stu_id
);与 in 示例完全一致,返回所有有成绩的学生。
exists 子查询中 select 1 是最优写法(无需查询实际字段,只判断是否有行)exists 性能远优于 in,尤其是大表场景(in 会全表扫描,exists 逐行匹配)in 适合子查询结果集小的场景,exists 适合子查询结果集大的场景| 子查询类型 | 关键字 | 子查询结果要求 | 核心逻辑 | 适用场景 |
|---|---|---|---|---|
| 比较运算符 | = > < | 单行单列 | 与标量值比较 | 单值条件过滤 |
in | in | 多行单列 | 匹配结果集中任意一个 | 多值匹配、去重筛选 |
any/some | any/some | 多行单列 | 满足任意一个 | 「比任意一个大 / 小」场景 |
all | all | 多行单列 | 满足所有 | 「比所有都大 / 小」场景 |
exists | exists | 任意(只看是否有行) | 关联匹配,返回 true/false | 大表关联、高性能筛选 |
子查询结果行数错误
in/any/all 要求子查询返回多行 1 列,否则逻辑错误not in 空值陷阱
null,not in 会返回空结果(因为 null 参与比较结果为 unknown)not exists 替代 not in,或在子查询中过滤 null关联子查询性能优化
exists 子查询中,关联字段必须加索引,否则性能骤降select *,用 select 1 最优子查询嵌套层级
-- 需求:查询二班中,成绩 > 一班所有学生成绩的学生信息
select s.stu_name, sc.subject, sc.score
from student s
join score sc on s.stu_id = sc.stu_id
where s.class = '二班'
and sc.score > all(
select sc2.score from score sc2
join student s2 on sc2.stu_id = s2.stu_id
where s2.class = '一班'
);| stu_name | subject | score |
|---|---|---|
| 孙七 | 语文 | 95 |
in:多值匹配,子查询返回多行单列any/some:任意满足,等价于「> 最小 / < 最大」all:全部满足,等价于「> 最大 / < 最小」exists:关联匹配,高性能,适合大表exists > in > 多层子查询not in 空值陷阱、关联字段加索引到此这篇关于mysql子查询5大核心用法的文章就介绍到这了,更多相关mysql子查询用法内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论