MySQL表的内连接与外连接详解

1. 内连接(INNER JOIN)

1.1 基本概念

内连接是利用WHERE子句对两种表形成的笛卡尔积进行筛选,只返回两个表中连接字段相等的行。

1.2 语法格式

复制代码
SELECT 字段 FROM 表1 INNER JOIN 表2 ON 连接条件 [AND 其他条件];

1.3 实际案例

显示SMITH的名字和部门名称

传统写法(我们之前学习的方式)
复制代码
SELECT ename, dname 
FROM EMP, DEPT 
WHERE EMP.deptno = DEPT.deptno AND ename = 'SMITH';
标准内连接写法
复制代码
SELECT ename, dname 
FROM EMP INNER JOIN DEPT ON EMP.deptno = DEPT.deptno 
WHERE ename = 'SMITH';

-- 或者将条件写在ON子句中
SELECT ename, dname 
FROM EMP INNER JOIN DEPT ON EMP.deptno = DEPT.deptno AND ename = 'SMITH';

1.4 内连接特点

  • 只显示两个表中匹配的记录

  • 不匹配的记录不会出现在结果中

  • 是开发中最常用的连接方式

2. 外连接(OUTER JOIN)

2.1 外连接概述

外连接分为左外连接和右外连接,用于显示不匹配的记录。

2.2 创建测试数据

复制代码
-- 学生表
CREATE TABLE stu (id int, name varchar(30));
INSERT INTO stu VALUES (1, 'jack'), (2, 'tom'), (3, 'kity'), (4, 'nono');

-- 成绩表
CREATE TABLE exam (id int, grade int);
INSERT INTO exam VALUES (1, 56), (2, 76), (11, 8);

3. 左外连接(LEFT JOIN)

3.1 基本概念

左外连接会返回左表的所有记录,以及右表中连接字段相等的记录。如果右表没有匹配的记录,则显示为NULL。

3.2 语法格式

复制代码
SELECT 字段名 FROM 表名1 LEFT JOIN 表名2 ON 连接条件;

3.3 实际案例

查询所有学生的成绩,如果学生没有成绩,也要显示学生信息

复制代码
SELECT * FROM stu LEFT JOIN exam ON stu.id = exam.id;

查询结果示例:

复制代码
+------+------+------+-------+
| id   | name | id   | grade |
+------+------+------+-------+
| 1    | jack | 1    | 56    |
| 2    | tom  | 2    | 76    |
| 3    | kity | NULL | NULL  |  -- 左表有记录,右表无匹配
| 4    | nono | NULL | NULL  |  -- 左表有记录,右表无匹配
+------+------+------+-------+

3.4 左外连接特点

  • 左表记录全部显示

  • 右表只显示匹配的记录

  • 不匹配的右表字段显示为NULL

4. 右外连接(RIGHT JOIN)

4.1 基本概念

右外连接会返回右表的所有记录,以及左表中连接字段相等的记录。如果左表没有匹配的记录,则显示为NULL。

4.2 语法格式

复制代码
SELECT 字段 FROM 表名1 RIGHT JOIN 表名2 ON 连接条件;

4.3 实际案例

显示所有成绩信息,即使没有对应的学生信息

复制代码
SELECT * FROM stu RIGHT JOIN exam ON stu.id = exam.id;

查询结果示例:

复制代码
+------+------+------+-------+
| id   | name | id   | grade |
+------+------+------+-------+
| 1    | jack | 1    | 56    |
| 2    | tom  | 2    | 76    |
| NULL | NULL | 11   | 8     |  -- 右表有记录,左表无匹配
+------+------+------+-------+

5. 综合练习与应用

5.1 实际业务场景

列出部门名称和员工信息,同时显示没有员工的部门

方法一:使用左外连接
复制代码
SELECT d.dname, e.* 
FROM dept d LEFT JOIN emp e ON d.deptno = e.deptno;
方法二:使用右外连接
复制代码
SELECT d.dname, e.* 
FROM emp e RIGHT JOIN dept d ON d.deptno = e.deptno;

5.2 多表外连接应用

复制代码
-- 显示所有部门、员工及工资等级信息
SELECT d.dname, e.ename, e.sal, s.grade
FROM dept d 
LEFT JOIN emp e ON d.deptno = e.deptno
LEFT JOIN salgrade s ON e.sal BETWEEN s.losal AND s.hisal;

6. 连接类型对比总结

连接类型 语法 结果描述 使用场景
内连接 INNER JOIN 只返回两个表匹配的记录 需要完全匹配的数据
左外连接 LEFT JOIN 返回左表全部+右表匹配记录 需要显示主表所有记录
右外连接 RIGHT JOIN 返回右表全部+左表匹配记录 需要显示从表所有记录

7. 实战技巧与注意事项

7.1 性能优化建议

复制代码
-- 好的实践:在连接条件上使用索引
SELECT * FROM emp e 
INNER JOIN dept d ON e.deptno = d.deptno  -- deptno字段应该有索引
WHERE e.sal > 2000;

-- 避免在连接条件中使用函数
SELECT * FROM emp e 
INNER JOIN dept d ON e.deptno = d.deptno  -- 好
-- 而不是:ON YEAR(e.hiredate) = YEAR(d.create_date)  -- 不好

7.2 复杂连接查询示例

复制代码
-- 查询每个部门的员工数量(包括没有员工的部门)
SELECT d.dname, COUNT(e.empno) as employee_count
FROM dept d 
LEFT JOIN emp e ON d.deptno = e.deptno
GROUP BY d.deptno, d.dname;

-- 查询没有员工的部门
SELECT d.dname
FROM dept d 
LEFT JOIN emp e ON d.deptno = e.deptno
WHERE e.empno IS NULL;

8. LeetCode实战题目

8.1 题目类型分析

  • rank-scores:需要使用自连接或窗口函数进行排名

  • exchange-seats:需要使用CASE语句和自连接进行座位交换

8.2 解题思路示例

复制代码
-- 类似rank-scores的解法思路
SELECT s1.score, COUNT(DISTINCT s2.score) as 'rank'
FROM scores s1, scores s2 
WHERE s1.score <= s2.score 
GROUP BY s1.id 
ORDER BY s1.score DESC;

9. 总结

9.1 核心要点

  1. 内连接:求交集,最常用

  2. 左外连接:保留左表全部记录

  3. 右外连接:保留右表全部记录

  4. 实际开发中根据业务需求选择合适的连接方式

9.2 选择指南

  • 需要完全匹配的数据 → 使用INNER JOIN

  • 需要显示主表所有记录(如:所有学生) → 使用LEFT JOIN

  • 需要显示从表所有记录(如:所有成绩) → 使用RIGHT JOIN

  • 多表连接时注意连接顺序和性能影响

掌握这些连接方式后,能够处理各种复杂的数据查询需求,是数据库开发的重要技能。

相关推荐
杜子不疼.几秒前
AI Agent 智能体开发入门:AutoGen 多智能体协作实战教程
java·人工智能·spring
樽酒ﻬق几秒前
构筑容器化基石:Docker 稳定版本抉择、极速安装与配置全解
java·docker·运维开发
XDHCOM3 分钟前
MySQL ER_IB_MSG_919报错解析,故障修复与远程处理指南
数据库·mysql·adb
爬山算法7 分钟前
MongoDB(88)如何进行数据迁移?
数据库·mongodb
weisian1517 分钟前
Java并发编程--29-分布式ID的6种方案:从单机到分库分表的“身份证”设计
java·分布式·雪花算法·美团leaf·百度uid
小小程序员.¥10 分钟前
oracle--函数
数据库·sql·mysql
Leon-Ning Liu10 分钟前
Oracle 26ai 新特性: True Cache(真实缓存)
数据库·缓存·oracle
Leon-Ning Liu11 分钟前
Oracle 26ai 的 SQL 语言增强特性
数据库·sql·oracle
美式请加冰12 分钟前
最短路径问题
java·数据结构·算法
Elastic 中国社区官方博客12 分钟前
Elasticsearch:语义搜索,现在默认支持多语言
大数据·数据库·人工智能·elasticsearch·搜索引擎·ai·全文检索