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 核心要点
内连接:求交集,最常用
左外连接:保留左表全部记录
右外连接:保留右表全部记录
实际开发中根据业务需求选择合适的连接方式
9.2 选择指南
需要完全匹配的数据 → 使用INNER JOIN
需要显示主表所有记录(如:所有学生) → 使用LEFT JOIN
需要显示从表所有记录(如:所有成绩) → 使用RIGHT JOIN
多表连接时注意连接顺序和性能影响
掌握这些连接方式后,能够处理各种复杂的数据查询需求,是数据库开发的重要技能。