跳到主要内容
极客日志极客日志
首页博客AI提示词GitHub精选代理工具
搜索
|注册
博客列表
SQLjava算法

MySQL 联合查询实战:多表关联与子查询详解

MySQL 联合查询用于从多个表中检索数据。涵盖内连接、外连接(左/右)、自连接及子查询的核心用法。通过笛卡尔积原理说明连接条件的重要性,演示 LEFT JOIN 处理缺失数据场景。讲解 UNION 与 UNION ALL 的区别,以及如何在 FROM 子句中使用临时表进行复杂过滤。最后介绍 INSERT INTO ... SELECT 语句实现数据迁移。掌握这些技巧可高效解决多表关联与数据聚合问题。

战神发布于 2026/3/23更新于 2026/5/35 浏览
MySQL 联合查询实战:多表关联与子查询详解

MySQL 联合查询实战

在数据库设计的范式下,数据往往分散在多个表中。当我们需要同时获取这些表的信息时,就必须使用联合查询(Join)将多个表连接起来。

笛卡尔积的陷阱

如果直接对两个表进行查询而不加限制,会产生笛卡尔积。例如:

SELECT * FROM student, class;

这会返回两个表行数的乘积,数据量会非常庞大且包含大量无效结果。正确的做法是加上 WHERE 条件,确保关联字段相等:

SELECT * FROM student, class WHERE student.class_id = class.id;

此时查询结果才合理。为了避免歧义,建议显式指定列名并使用表别名,特别是当不同表存在同名列时:

SELECT student.id, student.name, sex, student.class_id, class.id, class.name 
FROM student, class 
WHERE student.class_id = class.id;

联合查询基本步骤:

  1. 确定查询表(隐含笛卡尔积)
  2. 确定连接条件
  3. 加入过滤条件
  4. 精简查询列,建议使用表别名

内连接 (Inner Join)

内连接只返回两个表中连接字段相匹配的行。除了传统的逗号分隔写法,推荐使用标准的 JOIN 语法:

-- 传统写法
SELECT 字段 FROM 表 1 别名 1, 表 2 别名 2 WHERE 连接条件 AND 其他条件;

-- 标准写法
SELECT 字段 FROM 表 1 别名 1 INNER JOIN 表 2 别名 2 ON 连接条件 WHERE 其他条件;

示例:查询学生成绩

假设有课程、班级、学生、分数四张表。查询'唐三藏'的所有学科成绩:

SELECT s.name, sc.score 
FROM student AS s, score AS sc 
WHERE s.id = sc.student_id AND s.name = '唐三藏';

-- 或者使用 JOIN
SELECT s.name, sc.score 
FROM student AS s JOIN score sc ON s.id = sc.student_id AND s.name = '唐三藏';

若要查询所有学生的总成绩,需要配合 GROUP BY:

SELECT s.name, SUM(sc.score) 
FROM student AS s, score AS sc 
WHERE s.id = sc.student_id 
GROUP BY s.id;

外连接 (Outer Join)

MySQL 支持左外连接和右外连接,但不支持全外连接。

  • 左外连接 (LEFT JOIN):返回左表所有记录,右表无匹配则显示 NULL。
  • 右外连接 (RIGHT JOIN):返回右表所有记录,左表无匹配则显示 NULL。

左外连接应用

查询没有参加考试的学生。让 student 左外连接 score,若成绩为空则说明未考试:

SELECT s.id, s.name, sc.* 
FROM student s LEFT JOIN score sc ON s.id = sc.student_id;

-- 筛选出未考试的学生
SELECT s.id, s.name, s.class_id 
FROM student s LEFT JOIN score sc ON s.id = sc.student_id 
WHERE sc.score IS NULL;

右外连接应用

查询没有学生的班级。让 student 右外连接 class:

SELECT * FROM student s RIGHT JOIN class c ON s.class_id = c.id;

-- 筛选出没有学生的班级
SELECT * FROM student s RIGHT JOIN class c ON s.class_id = c.id 
WHERE s.id IS NULL;

自连接 (Self Join)

自连接是将表与自己进行连接,通常用于比较同一表中的不同行。必须给表起不同的别名,否则无法区分。

例如,查询 MySQL 成绩大于 Java 成绩的学生:

SELECT s1.*, s2.* 
FROM score s1, score s2, course c1, course c2 
WHERE s1.student_id = s2.student_id 
AND s1.course_id = c1.id 
AND s2.course_id = c2.id 
AND c1.NAME = 'MySQL' 
AND c2.NAME = 'java' 
AND s1.score > s2.score;

若想查看详细信息(含姓名、班级),需进一步关联 student 和 class 表:

SELECT stu.name AS 姓名, c.name AS 班级, s1.score AS MySQL, s2.score AS java 
FROM score s1, score s2, course c1, course c2, student stu, class c 
WHERE s1.student_id = s2.student_id 
AND s1.course_id = c1.id 
AND s2.course_id = c2.id 
AND stu.id = s1.student_id 
AND stu.class_id = c.id 
AND c1.NAME = 'MySQL' 
AND c2.NAME = 'java' 
AND s1.score > s2.score;

子查询 (Subquery)

子查询是指在一个查询语句中嵌套另一个查询,其结果可作为条件或临时表使用。

单行子查询

WHERE 条件中的子查询只返回一行数据,常用 = 或 IN。

例如,查询与'不想毕业'同学同班的所有学生:

SELECT * FROM student 
WHERE class_id = (SELECT class_id FROM student WHERE name = '不想毕业');

多列子查询

子查询返回多行或多列数据,通常配合 IN 使用。

查询选修了 MySQL 或 Java 课程的成绩:

SELECT * FROM score 
WHERE course_id IN (SELECT id FROM course WHERE name = 'MySQL' OR name = 'java');

FROM 子句中的子查询

MySQL 会自动为子查询创建临时表,可将其视为普通表进行连接或过滤。

例如,查询比'Java001 班'平均分高的成绩信息:

SELECT * FROM score s, 
(SELECT AVG(sc.score) AS score 
FROM score sc, class c, student s 
WHERE c.id = s.class_id AND sc.student_id = s.id AND c.NAME = 'java001 班') tmp 
WHERE s.score > tmp.score;

合并查询 (Union)

使用 UNION 操作符合并多个 SELECT 的结果集。

  • UNION:自动去除重复行。
  • UNION ALL:保留所有行,包括重复项,性能更高。

示例:合并 student 表中 ID<3 的同学与 student1 表中的所有同学:

SELECT * FROM student WHERE id < 3 
UNION 
SELECT * FROM student1;

-- 不去重
SELECT * FROM student WHERE id < 3 
UNION ALL 
SELECT * FROM student1;

插入查询结果

可以将一个查询的结果直接插入到另一个表中:

INSERT INTO table_name [(column, ...)] SELECT ...;

例如,将 student 表中'C++001 班'的学生复制到 student1 表:

INSERT INTO student1 (name, class_id) 
SELECT s.name, s.class_id 
FROM student s, class c 
WHERE s.class_id = c.id AND c.name = 'C++001 班';

目录

  1. MySQL 联合查询实战
  2. 笛卡尔积的陷阱
  3. 内连接 (Inner Join)
  4. 示例:查询学生成绩
  5. 外连接 (Outer Join)
  6. 左外连接应用
  7. 右外连接应用
  8. 自连接 (Self Join)
  9. 子查询 (Subquery)
  10. 单行子查询
  11. 多列子查询
  12. FROM 子句中的子查询
  13. 合并查询 (Union)
  14. 插入查询结果
  • 💰 8折买阿里云服务器限时8折了解详情
  • GPT-5.5 超高智商模型1元抵1刀ChatGPT中转购买
  • 代充Chatgpt Plus/pro 帐号了解详情
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 医疗连续体机器人模块化控制界面设计与 Python 库应用
  • AI 视频生成工具清单及免费额度说明
  • Stack-Chan 机器人开发指南
  • Linux Mint 22.3 安装指南与系统优化实战
  • 论文 AI 检测率过高?八种实用方法降低机器痕迹
  • OpenAI DALL·E API 绘图实战:从零构建 AI 绘画应用
  • Python Mode for Processing 创意编程使用指南
  • 传统线程同步通讯技术实现
  • VS Code + WSL 环境下 GitHub 访问及 Copilot 连接问题解决方案
  • Levenberg-Marquardt 非线性最小二乘优化算法 C++ 实战实现
  • 昇腾平台下 DeepSeek-R1 与 Qwen2.5 强化学习训练优化实践
  • Clawdbot 整合 Qwen3-32B 本地部署与 Web 访问指南
  • Spring Cloud 微服务全栈实践:从认知到落地
  • Linux Shell 脚本中的 for 循环语句详解
  • 如何在 GitHub Copilot 中使用 MCP 服务
  • AI Agent 开发入门:零基础学习指南
  • C++ 进阶:AVL 树的原理与实现
  • LLaMA 系列模型演进:从 Llama-1 到 Llama-3 的技术发展与对比
  • 基于 Whisper-large-v3 的多语言翻译系统开发
  • Spring Boot 安全认证与授权实战

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online