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

相关推荐
大鹏说大话2 小时前
消息队列 Kafka/RabbitMQ/RocketMQ 怎么选?业务场景对比指南
开发语言
IT WorryFree2 小时前
OpenClaw 对接飞书 Debug 指南
开发语言·php·飞书
码云数智-大飞2 小时前
JVM 调优实战:内存溢出、GC 频繁问题定位思路
开发语言
Henray20242 小时前
SQL 窗口函数
大数据·数据库·sql
顶点多余2 小时前
Mysql--索引的操作
数据库·mysql
AsDuang2 小时前
Python 3.12 MagicMethods - 48 - __rmatmul__
开发语言·python
lsx2024062 小时前
Django 视图 - FBV 与 CBV
开发语言
RDCJM2 小时前
Neo4j图数据库学习(二)——SpringBoot整合Neo4j
数据库·学习·neo4j
不会写DN2 小时前
如何让两个Go程序远程调用?
开发语言·qt·golang