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

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

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

相关推荐
Nandeska2 小时前
14、MySQL基于GTID的数据同步
数据库·mysql
Amumu121382 小时前
Vue Router(一)
前端·javascript·vue.js
索荣荣2 小时前
Java正向代理与反向代理实战指南
java·开发语言
郑州光合科技余经理2 小时前
可独立部署的Java同城O2O系统架构:技术落地
java·开发语言·前端·后端·小程序·系统架构·uni-app
清山博客2 小时前
jQuery easyui 扩展datetimebox控件,增加上午、中午、下午快速选择
前端·jquery·easyui
l1t2 小时前
DeepSeek辅助总结postgresql wiki提供的数独求解器
数据库·sql·postgresql
appearappear2 小时前
大数据量处理
数据库
笨蛋不要掉眼泪2 小时前
Spring Boot + RedisTemplate 数据结构的基础操作
java·数据结构·spring boot·redis·wpf