MySQL 高阶语句是数据库查询、数据处理的核心能力,主要包括子查询 、连接查询 (内连接、外连接)、多表关联查询等,以下结合文档核心内容+实用拓展,系统总结:
一、子查询(Subquery)
1. 核心定义(文档核心)
子查询是嵌套在其他 SQL 语句(SELECT/INSERT/UPDATE/DELETE)中的查询语句,其结果作为外层查询的「条件」「数据源」或「计算依据」,本质是"用一个查询辅助另一个查询"。
2. 核心作用
作为外层查询的过滤条件(如 WHERE 子句中);
作为外层查询的数据源(如 FROM 子句中,也称"派生表");
作为字段值(如 SELECT 子句中,需返回单行单列结果)。
3. 分类(面试高频)
按返回结果类型可分为 4 类,对应不同使用场景:
| 子查询类型 | 返回结果 | 常用关键字 | 适用场景 |
|---|---|---|---|
| 单行子查询 | 单个值(1 行 1 列) | =、>、<、>=、<= | 外层查询需单个条件匹配(如查询"工资高于部门平均工资的员工") |
| 多行子查询 | 多个值(多行 1 列) | IN、NOT IN、ANY、ALL | 外层查询需匹配多个条件(如查询"属于销售部或技术部的员工") |
| 多列子查询 | 多个字段(多行多列) | IN(需字段数匹配) | 外层查询需多字段联合匹配(如查询"与某员工部门+岗位都相同的人") |
| 关联子查询 | 依赖外层查询的参数(逐行执行) | EXISTS、NOT EXISTS | 需判断"存在性"(如查询"有下属的部门"),效率常优于 IN 子查询 |
4. 实用示例
(1)单行子查询(=)
SQL
-- 查询工资高于部门平均工资的员工(部门 ID=3)
SELECT name, salary
FROM employees
WHERE dept_id=3 AND salary > (
SELECT AVG(salary) FROM employees WHERE dept_id=3
);
(2)多行子查询(IN)
SQL
-- 查询"销售部"或"技术部"的员工(先查部门 ID,再匹配员工)
SELECT name, dept_id
FROM employees
WHERE dept_id IN (
SELECT id FROM departments WHERE dept_name IN ('销售部', '技术部')
);
(3)关联子查询(EXISTS)
SQL
-- 查询有下属的部门(依赖外层部门 ID,判断是否存在对应员工)
SELECT dept_name
FROM departments d
WHERE EXISTS (
SELECT 1 FROM employees e WHERE e.dept_id = d.id
);
二、连接查询(JOIN)
连接查询用于关联多个表的数据,核心是通过「共同字段」(如主键-外键)建立关联,文档重点讲了内连接、左连接、右连接,以下补充全连接、自连接及优化要点。
1. 核心连接类型
| 连接类型 | 定义(核心逻辑) | 语法 | 不匹配记录处理 | 适用场景 |
|---|---|---|---|---|
| 内连接(INNER JOIN) | 只返回两表中「满足连接条件」的记录 | SELECT ... FROM 表A INNER JOIN 表B ON 表A.字段=表B.字段; | 全部过滤 | 需获取两表"交集"数据(如匹配员工和其部门信息) |
| 左连接(LEFT JOIN) | 以「左表」为基准,返回左表所有记录 + 右表匹配记录 | SELECT ... FROM 表A LEFT JOIN 表B ON 表A.字段=表B.字段; | 右表字段填充 NULL | 需保留左表全部数据(如查询所有员工,即使未分配部门) |
| 右连接(RIGHT JOIN) | 以「右表」为基准,返回右表所有记录 + 左表匹配记录 | SELECT ... FROM 表A RIGHT JOIN 表B ON 表A.字段=表B.字段; | 左表字段填充 NULL | 需保留右表全部数据(如查询所有部门,即使无员工) |
| 全连接(FULL JOIN) | 返回两表所有记录,匹配的合并,不匹配的填充 NULL | MySQL 不直接支持,用:LEFT JOIN UNION RIGHT JOIN | 两边不匹配字段均为 NULL | 需获取两表"全集"数据(如合并两个表的所有记录) |
2. 自连接(SELF JOIN)
自连接是「表与自身的连接」,需通过别名区分两个"虚拟表",常用于查询"具有层级关系"或"自身关联"的数据(如员工与上级、分类与子分类)。
示例:查询员工及其直接上级
SQL
-- 员工表 employees(id, name, manager_id),manager_id 关联自身 id
SELECT e.name AS 员工姓名, m.name AS 上级姓名
FROM employees e
LEFT JOIN employees m ON e.manager_id = m.id;
3. 连接查询的核心注意事项
「ON vs WHERE」:ON 是「连接条件」(筛选关联的记录),WHERE 是「最终过滤条件」(筛选已关联后的记录);
避免笛卡尔积:必须指定连接条件(ON 子句),否则两表会全量关联(如 1000 行 × 1000 行 = 100 万行,性能极差);
索引优化:连接字段(如主键、外键)建议创建索引,可大幅提升连接效率。
三、多表关联查询(3 张及以上表)
1. 实现方式
通过「连续使用 JOIN 子句」关联多张表,每个 JOIN 都需指定"关联表"和"连接条件",建议使用表别名(如 s 代表 students)简化 SQL。
2. 经典示例
假设有 3 张表:
students(id:学生 ID,name:学生姓名)
scores(id:成绩 ID,student_id:关联学生 ID,course_id:关联课程 ID,score:分数)
courses(id:课程 ID,course_name:课程名称)
需求:查询"所有学生的姓名、所选课程名称及对应分数"(含未选课的学生)
SQL
SELECT
s.name AS 学生姓名,
c.course_name AS 课程名称,
sc.score AS 分数
FROM students s -- 左表:学生表(保留所有学生)
LEFT JOIN scores sc ON s.id = sc.student_id -- 关联成绩表(学生-成绩)
LEFT JOIN courses c ON sc.course_id = c.id; -- 关联课程表(成绩-课程)
3. 多表连接拓展技巧
关联顺序:优先关联数据量小的表(如字典表、分类表),再关联大表(如订单表、用户表),提升查询效率;
字段歧义:多表中若有同名字段(如 id),必须通过「表别名.字段名」指定(如 <s.id>、<sc.id>),否则 SQL 报错;
过滤条件:多表连接时,过滤条件尽量写在对应表的 ON 子句中(如只查"数学"课程,可在 courses 关联时加 ON sc.course_id = c.id AND c.course_name='数学'),减少关联后的数据量。
四、高阶查询优化建议(面试高频补充)
-
子查询 vs 连接查询:简单子查询可直接使用,复杂子查询(如多层嵌套)建议改为连接查询(JOIN),因为 MySQL 对连接查询的优化更成熟,效率更高;
-
索引设计:子查询的条件字段、连接查询的关联字段,建议创建 B+ 树索引(如 student_id、course_id),避免全表扫描;
-
限制返回结果:使用 LIMIT 限制返回行数,避免大数据量查询拖慢数据库;
-
避免 SELECT *:只查询需要的字段,减少数据传输和内存占用。
总结
MySQL 高阶语句的核心是「灵活组合子查询与连接查询」,解决多表数据关联、复杂条件筛选的需求。