SQL:JOIN 进阶

发布于:2025-05-13 ⋅ 阅读:(19) ⋅ 点赞:(0)

目录

JOIN 是什么?

 🔹OUTER JOIN(外连接)

外连接的分类

外连接与内连接的区别

🔹USING 子句 

语法结构

 和 ON 的对比

📘USING 的内部逻辑 

🧩 多个字段的 USING

USING 的 SELECT 特性(字段可见性)

配合 JOIN 类型的效果

🔹NATURAL JOIN(自然连接)

基本语法:

🔄 执行机制

🔍 对比示例

隐藏风险 ⚠️ 

字段选择行为(结果特征)

自然连接的变体语法(扩展)

NATURAL JOIN vs USING vs ON

🧩 JOIN 的本质回顾:有条件的笛卡尔积


JOIN 是什么?

JOIN 本质上是“笛卡尔积 + 条件筛选”。

在关系数据库中,两个表的连接最原始的操作就是笛卡尔积,即将表 A 和表 B 的所有行做组合,然后通过连接条件筛选我们真正需要的数据。

本篇文章将从以下几个方面,带你走进 JOIN 的进阶世界:

  • 外连接的完整逻辑

  • 更优雅的连接方式:USING 子句

  • 自动化但需谨慎使用的 NATURAL JOIN


 🔹OUTER JOIN(外连接)

在实际开发中,我们常常使用 INNER JOIN 来筛选匹配成功的数据行。然而,这种连接方式默认忽

略未匹配的记录,在某些业务场景(如数据缺失分析、审计对比、错误检测)中反而是不利的。 

外连接是一种可以保留未匹配记录的连接方式,它不仅保留匹配成功的行,还会保留某一方或双方

表中未能匹配的行,并对缺失部分用 NULL 补全。 

外连接的分类

类型 含义说明
LEFT OUTER JOIN 保留左表所有记录,右表无法匹配的补 NULL
RIGHT OUTER JOIN 保留右表所有记录,左表无法匹配的补 NULL
FULL OUTER JOIN 保留左右两表所有记录,无法匹配部分用 NULL 补全

📌 注意:通常 SQL 中 OUTER 关键字可以省略。

外连接与内连接的区别

比较维度 INNER JOIN OUTER JOIN(LEFT/RIGHT/FULL)
匹配条件 只保留匹配成功的行 匹配成功 + 不匹配的行(补 NULL)
连接结果 小于等于原始行数 大于等于参与表的行数
典型使用场景 严格一一匹配需求 需要查看未关联数据

⚠️ MySQL 不直接支持 FULL OUTER JOIN 


 

🔹USING 子句 

我们在之前的 JOIN 中,经常会写出类似 ON a.id = b.id 的重复性语句。USING 是一种语法糖,

当连接字段在两个表中字段名完全一致时,它可以大幅度简化写法。

USING 子句是 JOIN 中的语法简写,用于当连接字段在两个表中字段名相同时,代替 ON a.col = b.col 的写法。

语法结构

SELECT column_list
FROM table1
JOIN table2
USING (column_name);

多个字段:

SELECT column_list
FROM table1
JOIN table2
USING (column1, column2);

🔸 支持:INNER JOINLEFT JOINRIGHT JOINFULL OUTER JOIN
🔸 不支持:CROSS JOIN(因为它没有连接条件)

⚠️ 注意事项

  1. USING 中指定的字段必须在两个表中都存在且字段名一致

  2. 仅支持等值连接(=

  3. SELECT 出来的结果中,这些字段只会显示一次(不是 table1.col 和 table2.col,而是一个简化字段)

 和 ON 的对比

使用 ON 的写法:

SELECT *
FROM employees e
JOIN departments d
ON e.dept_id = d.dept_id;

等价的 USING 写法:

SELECT *
FROM employees
JOIN departments
USING (dept_id);

💡 两者效果一致,差异是:

  • ON 写法结果中会保留 e.dept_idd.dept_id 两列;

  • USING 写法只保留一列 dept_id,更整洁。

📘USING 的内部逻辑 

在执行阶段,SQL 引擎会将:

JOIN USING (col)

转换为:

JOIN ON table1.col = table2.col

然后只保留一个 col 字段,不显示来源表名。

🧩 多个字段的 USING

你可以使用多个字段作为连接条件(必须字段名都一样):

SELECT *
FROM orders o
JOIN deliveries d
USING (order_id, delivery_date);

 这相当于:

ON o.order_id = d.order_id AND o.delivery_date = d.delivery_date

USING 的 SELECT 特性(字段可见性)

考虑如下例子:

SELECT *
FROM employees
JOIN departments
USING (dept_id);

结果中:

  • dept_id 只出现一次

  • 你不能在 SELECT 中写 employees.dept_iddepartments.dept_id,会报错

💡 所以在使用 USING 时,如果你需要区分字段来源,就不要用 USING,用 ON 更灵活

配合 JOIN 类型的效果

JOIN 类型 是否支持 USING 非匹配字段是否保留 输出字段
INNER JOIN 公共字段只显示一次
LEFT JOIN 左表全部保留 同上
RIGHT JOIN 右表全部保留 同上
FULL OUTER JOIN ✅(部分数据库) 两表全部保留 同上

🔹NATURAL JOIN(自然连接)

NATURAL JOIN 是一种自动基于两个表中相同列名进行连接的语法,无需显式指定连接条件。 

基本语法:

SELECT column_list
FROM table1
NATURAL JOIN table2;

支持的连接类型有:

  • NATURAL JOIN(即自然内连接)

  • NATURAL LEFT JOIN

  • NATURAL RIGHT JOIN

  • NATURAL FULL OUTER JOIN(部分数据库支持)

🔄 执行机制

自然连接的执行过程分为三步:

  1. 自动识别两个表中字段名相同的列

  2. 对这些列执行等值连接(相当于 ON a.col = b.col)

  3. 结果中只保留一份这些列,不重复显示

 注意:这是隐式行为,你无法控制哪些字段被用于连接,只要名字一样,它就会加入连接条件中。

🔍 对比示例

我们以两个表为例:

表A:students

id

name

class_id

1

Alice

101

2

Bob

102

表B:classes

class_id teacher
101 Zhang
102 Wang

 使用 NATURAL JOIN:

SELECT *
FROM students
NATURAL JOIN classes;

 相当于:

SELECT students.id, students.name, students.class_id, classes.teacher
FROM students
JOIN classes
ON students.class_id = classes.class_id;

但注意:

  • class_id 只显示一列,不是 students.class_idclasses.class_id 两列。

隐藏风险 ⚠️ 

虽然语法简洁,但 NATURAL JOIN 有两个致命隐患:

1️⃣ 字段名意外冲突

如果两个表中存在同名但不相关的列,它们也会被自动用于连接,可能导致:

  • 错误连接逻辑

  • 无结果

  • 数据误导

示例:

-- students 和 exams 表都有 name 字段,但不是用于连接的
SELECT *
FROM students
NATURAL JOIN exams;

这里 name 字段会被用于连接,结果可能完全不符合预期。

2️⃣ 表结构变动敏感

只要某个字段名在两个表中变得相同(或不同),NATURAL JOIN 的行为会自动改变,增加 SQL 的不可预测性与维护难度。

字段选择行为(结果特征)

  • 所有同名字段:只显示一列(不带表前缀)

  • 非同名字段:分别显示原始表字段

自然连接的变体语法(扩展)

类型 说明
NATURAL JOIN 自然内连接(只返回匹配行)
NATURAL LEFT JOIN 左自然外连接(左表全部保留)
NATURAL RIGHT JOIN 右自然外连接(右表全部保留)
NATURAL FULL OUTER JOIN 全自然外连接(两个表全部保留)

⚠️ FULL OUTER 在 MySQL 中不支持。

NATURAL JOIN vs USING vs ON

特性 NATURAL JOIN USING 子句 ON 子句
连接字段是否自动识别 ✅(自动找同名字段) ❌(手动指定) ❌(完全手动)
是否必须字段名一致 ✅ 必须一致 ✅ 仅 USING 中字段需一致 ❌ 不要求一致
连接条件是否灵活 ❌ 只能等值 ❌ 只能等值 ✅ 任意逻辑、范围比较等
SELECT 中字段出现情况 同名字段只出现一次 USING 字段只出现一次 字段全部保留
可控性 ❌ 极低 ✅ 中等 ✅✅ 极高
推荐使用 ❌ 不推荐 ✅ 推荐 ✅✅ 强烈推荐

🧩 JOIN 的本质回顾:有条件的笛卡尔积

JOIN 的底层其实是生成两个表的笛卡尔积,再通过连接条件进行筛选,不同 JOIN 类型只是在“保留未匹配数据”的策略上不同。

 


网站公告

今日签到

点亮在社区的每一天
去签到