子查询Subquery也叫嵌套查询是 MySQL 中在一个查询语句内部嵌套另一个查询的高级语法能实现复杂的多表关联、条件过滤、数据筛选是 SQL 进阶的核心知识点。本文围绕图片中的 5 大类子查询从语法、逻辑、代码示例三个维度带你彻底掌握 MySQL 子查询。一、子查询基础概念1. 核心定义子查询嵌套在SELECT/INSERT/UPDATE/DELETE语句中的SELECT语句也叫「内查询」外层查询包含子查询的主语句也叫「外查询」执行顺序先执行子查询再执行外层查询子查询的结果作为外层查询的条件 / 数据源2. 准备测试数据创建两张关联表用于所有示例学生表studentCREATE 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);成绩表scoreCREATE 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);二、5 大类子查询详解1. 带比较运算符的子查询最基础核心逻辑用 !等比较运算符将外层查询的字段与子查询返回的单行单列结果进行比较。要求子查询必须返回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_namesubjectscore李四数学88孙七语文95说明子查询先算出二班平均分(788895)/3 ≈ 87外层查询筛选出二班中成绩 87 的学生。2. 带IN关键字的子查询最常用核心逻辑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);运行结果IN 示例stu_idstu_nameclassage1张三一班182李四二班193王五一班184赵六三班205孙七二班19说明子查询先查出所有有成绩的stu_id外层查询用IN匹配学生表筛选出对应学生。3. 带ANY/SOME关键字的子查询核心逻辑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_namesubjectscore张三数学92李四数学88王五数学88孙七语文95说明一班成绩为[85,92,88] ANY等价于 85最小值因此所有 85 的成绩都会被筛选出来。4. 带ALL关键字的子查询核心逻辑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_namesubjectscore孙七语文95说明一班最高分为92 ALL等价于 92因此只有孙七的 95 分满足条件。5. 带EXISTS关键字的子查询关联子查询核心逻辑EXISTS是关联子查询子查询会引用外层查询的字段执行逻辑为外层查询逐行遍历表子查询用当前行的字段进行查询若子查询返回至少 1 行结果则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适合子查询结果集大的场景三、核心对比与避坑指南1. 5 大类子查询核心区别子查询类型关键字子查询结果要求核心逻辑适用场景比较运算符 单行单列与标量值比较单值条件过滤ININ多行单列匹配结果集中任意一个多值匹配、去重筛选ANY/SOMEANY/SOME多行单列满足任意一个「比任意一个大 / 小」场景ALLALL多行单列满足所有「比所有都大 / 小」场景EXISTSEXISTS任意只看是否有行关联匹配返回 true/false大表关联、高性能筛选2. 常见避坑子查询结果行数错误比较运算符要求子查询必须返回1 行 1 列否则报错IN/ANY/ALL要求子查询返回多行 1 列否则逻辑错误NOT IN空值陷阱若子查询结果包含NULLNOT IN会返回空结果因为NULL参与比较结果为UNKNOWN解决方案用NOT EXISTS替代NOT IN或在子查询中过滤NULL关联子查询性能优化EXISTS子查询中关联字段必须加索引否则性能骤降避免在子查询中使用SELECT *用SELECT 1最优子查询嵌套层级MySQL 支持多层子查询嵌套但层级过多会严重影响性能尽量用连接查询替代四、综合实战多子查询组合-- 需求查询二班中成绩 一班所有学生成绩的学生信息 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_namesubjectscore孙七语文95五、核心总结子查询本质嵌套查询先内后外子查询结果作为外层条件5 大核心用法比较运算符单值比较子查询必须返回标量IN多值匹配子查询返回多行单列ANY/SOME任意满足等价于「 最小 / 最大」ALL全部满足等价于「 最大 / 最小」EXISTS关联匹配高性能适合大表性能优先级EXISTSIN 多层子查询避坑关键注意子查询结果行数、NOT IN空值陷阱、关联字段加索引