SQL表连接

想象你手上有两张表:

示例数据

员工表 Employees

复制代码
员工ID  | 姓名    | 部门ID
--------|---------|--------
1       | 张三    | 10
2       | 李四    | 20
3       | 王五    | 30
4       | 赵六    | NULL

部门表 Departments

复制代码
部门ID  | 部门名称
--------|----------
10      | 技术部
20      | 销售部
50      | 人事部

1. **INNER JOIN(内连接)**​ - 只要"匹配的"

inner可以省略

复制代码
SELECT e.姓名, d.部门名称
FROM Employees e
INNER JOIN Departments d ON e.部门ID = d.部门ID;

结果

复制代码
姓名    | 部门名称
--------|----------
张三    | 技术部
李四    | 销售部

解释 :只返回两张表都有匹配的记录。王五(部门ID=30)和赵六(部门ID=NULL)没有匹配的部门,所以不显示。


2. **LEFT JOIN(左连接)**​ - "左边的全要,右边的能配上就配"

复制代码
SELECT e.姓名, d.部门名称
FROM Employees e
LEFT JOIN Departments d ON e.部门ID = d.部门ID;

结果

复制代码
姓名    | 部门名称
--------|----------
张三    | 技术部
李四    | 销售部
王五    | NULL      ← 部门ID=30没找到
赵六    | NULL      ← 部门ID=NULL

解释 :以**左表(Employees)**为主,左表所有记录都显示,右表匹配不上就显示NULL。


3. **RIGHT JOIN(右连接)**​ - "右边的全要,左边的能配上就配"

复制代码
SELECT e.姓名, d.部门名称
FROM Employees e
RIGHT JOIN Departments d ON e.部门ID = d.部门ID;

结果

复制代码
姓名    | 部门名称
--------|----------
张三    | 技术部
李四    | 销售部
NULL    | 人事部    ← 部门ID=50没员工

解释 :以**右表(Departments)**为主,右表所有记录都显示,左表匹配不上就显示NULL。


4. **FULL JOIN(全连接)**​ - "我全都要"

复制代码
SELECT e.姓名, d.部门名称
FROM Employees e
FULL JOIN Departments d ON e.部门ID = d.部门ID;

结果

复制代码
姓名    | 部门名称
--------|----------
张三    | 技术部
李四    | 销售部
王五    | NULL      ← 员工有,部门无
赵六    | NULL      ← 员工有,部门无
NULL    | 人事部    ← 部门有,员工无

解释:左右表所有记录都显示,匹配不上就用NULL补全。


5. **CROSS JOIN(交叉连接)**​ - "所有组合"

复制代码
SELECT e.姓名, d.部门名称
FROM Employees e
CROSS JOIN Departments d;

结果:4个员工 × 3个部门 = 12行

复制代码
姓名    | 部门名称
--------|----------
张三    | 技术部
张三    | 销售部
张三    | 人事部
李四    | 技术部
李四    | 销售部
李四    | 人事部
...     | ...

ON 条件怎么理解?

ON条件就像是连接条件,告诉数据库怎么把两表的行"配对"。

例子1:等值连接(最常用)

复制代码
ON e.部门ID = d.部门ID

把员工表的部门ID和部门表的部门ID相等的行连在一起。

例子2:不等连接

复制代码
ON e.工资 > d.最低工资

连接那些员工工资大于部门最低工资的行。

例子3:多条件连接

复制代码
ON e.部门ID = d.部门ID 
   AND e.入职日期 > '2020-01-01'

既要部门ID相等,又要员工是2020年以后入职的。


JOIN 执行顺序可视化

复制代码
FROM 左表
LEFT JOIN 右表 ON 连接条件
WHERE 过滤条件

重要区别

  • ON:连接时的匹配条件(决定怎么连)

  • WHERE:连接后的过滤条件(决定显示哪些)

示例对比:

复制代码
-- ON 影响连接结果
SELECT * 
FROM A LEFT JOIN B 
ON A.id = B.id AND B.status = 'active';
-- 先按条件连接,再显示所有A的记录

-- WHERE 在连接后过滤  
SELECT *
FROM A LEFT JOIN B ON A.id = B.id
WHERE B.status = 'active';
-- 先连接,然后过滤掉B.status不是active的行
-- 注意:这会把B为NULL的行也过滤掉!

记忆口诀

  • INNER JOIN:只要"配对的"

  • LEFT JOIN:左表全要,右边"爱配不配"

  • RIGHT JOIN:右表全要,左边"爱配不配"

  • FULL JOIN:两个全要,"不配就NULL"

  • ON:是"介绍人",负责两边怎么认识

  • WHERE:是"家长",见面后还要筛选

实战建议

  1. 大部分情况用 LEFT JOIN(以主表为基准)

  2. 明确知道只要交集用 INNER JOIN

  3. ON条件尽量用索引字段(如ID)

  4. 复杂的过滤放WHERE,简单的匹配放ON

相关推荐
黑臂麒麟9 分钟前
HarmonyOS鸿蒙实战应用6:随手账本——Preferences本地持久化
数据库·华为·app·鸿蒙
孙克旭_13 分钟前
单链表进阶实操:5 道常考面试题详细解析【Java 实现】
java·开发语言·数据结构·单链表
斑马13918 分钟前
Linux软件编程学习笔记(五)——线程
开发语言·php
2601_9619017019 分钟前
SpringCloud2023集成Nacos2.4.3
java
玄昌盛不会编程21 分钟前
LeetCode——2091. 从数组中移除最大值和最小值
java·算法·leetcode
Rain的Java大神之路24 分钟前
如何保证接口幂等
java·经验分享·后端·面试·架构
吴声子夜歌25 分钟前
Java——数组和集合(一)
java·开发语言
Jesse_EC26 分钟前
一个看不见的字符——CRLF 如何让我的 Docker 初始化脚本"静默失踪"
java·后端
深念Y27 分钟前
Nuxt 项目 Docker 构建:从 pnpm+node 迁移到全 bun
java·前端·docker