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 小时前
mybatis的typeHandler 作用
数据库·mybatis
星栈独行2 小时前
翻完 Pi 源码:它和 Codex、Claude Code 有何不同
开发语言·javascript·人工智能·程序人生
pxzsky2 小时前
PG17数据库安装中分分词插件:pg_jieba
数据库·postgresql·pg_jieba
spencer_tseng2 小时前
Redis + Nacos.bat
java·windows·dos
qq_448011162 小时前
C语言中的变量和函数的定义与声明
android·c语言·开发语言
她说可以呀3 小时前
Redis哨兵
数据库·redis·bootstrap
troyzhxu3 小时前
列表查询的 GraphQL —— 一行代码终结你的 if-else 地狱!
java·springboot·graphql
霸道流氓气质3 小时前
KMS 密钥管理服务(Key Management Service)原理与实践
linux·服务器·数据库
kirs_ur3 小时前
CXL(Compute Express Link)— 内存扩展的未来
服务器·数据库·性能优化
孫治AllenSun4 小时前
【DataX】生产环境搭建DataX集群案例
java·开发语言·jvm