MySQL 高阶查询语句:子查询、连接查询与多表关联

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='数学'),减少关联后的数据量。

四、高阶查询优化建议(面试高频补充)

  1. 子查询 vs 连接查询:简单子查询可直接使用,复杂子查询(如多层嵌套)建议改为连接查询(JOIN),因为 MySQL 对连接查询的优化更成熟,效率更高;

  2. 索引设计:子查询的条件字段、连接查询的关联字段,建议创建 B+ 树索引(如 student_id、course_id),避免全表扫描;

  3. 限制返回结果:使用 LIMIT 限制返回行数,避免大数据量查询拖慢数据库;

  4. 避免 SELECT *:只查询需要的字段,减少数据传输和内存占用。

总结

MySQL 高阶语句的核心是「灵活组合子查询与连接查询」,解决多表数据关联、复杂条件筛选的需求。

相关推荐
天下无敌笨笨熊2 小时前
kotlin函数式编程
开发语言·数据库·kotlin
SHIPKING3932 小时前
【开发策略】MCP 多表查询策略方案
数据库·oracle
kka杰2 小时前
MYSQL 事务-1
数据库·mysql·oracle
chian_ocean3 小时前
在 KubeSphere 上部署 AI 大模型 Ollama
数据库
跟着珅聪学java3 小时前
Jedis SetParams教程:参数化设置 Redis 键值对
数据库·redis·缓存
一颗宁檬不酸3 小时前
数据库开发实战案例分享:从函数到存储过程的应用
数据库·数据库开发
北京中邦兴业3 小时前
GMP洁净环境监测法规深度解读:构建以风险为核心的动态防御体系
数据库·人工智能·面试·职场和发展
TDengine (老段)3 小时前
人力减 60%:时序数据库 TDengine 助力桂冠电力实现 AI 智能巡检
java·大数据·数据库·人工智能·时序数据库·tdengine·涛思数据
潇I洒3 小时前
Ubuntu Linux 24.04 安装MySQL 8.4.7
linux·数据库·mysql·ubuntu