logo

额外区块类型 (EBT) - 全新的布局构建器体验❗

额外区块类型 (EBT) - 样式化、可定制的区块类型:幻灯片、标签页、卡片、手风琴等更多类型。内置背景、DOM Box、JavaScript 插件的设置。立即体验布局构建的未来。

演示 EBT 模块 下载 EBT 模块

❗额外段落类型 (EPT) - 全新的 Paragraphs 体验

额外段落类型 (EPT) - 类似的基于 Paragraph 的模块集合。

演示 EPT 模块 滚动

滚动

PHP课程 - 第3.6课 - 使用MySQL数据库。JOIN操作符的类型。

09/10/2025, by Ivan

在 MySQL 中,可以通过多种方式使用 JOIN 进行数据选择。我们将尝试逐一讲解所有这些类型的查询。以下是所有涉及 JOIN 的查询列表:

  1. INNER JOIN(内连接)
  2. LEFT JOIN(左连接)
  3. LEFT JOIN(不与右表交集的左连接)
  4. RIGHT JOIN(右连接)
  5. RIGHT JOIN(不与左表交集的右连接)
  6. FULL OUTER JOIN(全外连接)
  7. FULL OUTER JOIN(左表或右表为空时)

 

以下是这些 JOIN 类型的示意图:

SQL

我将把我们网站的文件附加到文章中,其中包括 join.php 文件,我将在其中使用不同的 JOIN 操作符来输出所有记录。

INNER JOIN(内连接)

我们从 INNER JOIN 开始,因为如果在查询中仅写 JOIN,它默认就是 INNER JOIN。该操作符从两张表中选取满足 ON 条件的所有记录。我们有两张表:Files 和 Messages:

Messages 表:

mid bodytext fid
1 Test NULL
2 Hi 2
3 Hello NULL

 Files 表:

fid path
1 /files/1.png
2 /files/2.png
3 /files/3.png

JOIN 查询如下:

SELECT * FROM Messages INNER JOIN Files ON Messages.fid=Files.fid

结果如下:

mid bodytext fid path
2 Hi 2 /files/2.png

也就是说,只有当 fid 相同时,MySQL 才会输出这些行。

LEFT JOIN(左连接)

使用 LEFT JOIN 时,我们输出左表(此处为 Messages)中的所有记录,包括那些在右表(Files)中存在匹配 fid 的记录。

Messages 表:

mid bodytext fid
1 Test 2
2 Hi NULL
3 Hello 3

 Files 表:

fid path
1 /files/1.png
2 /files/2.png
3 /files/3.png

LEFT JOIN 查询如下:

SELECT * FROM Messages LEFT JOIN Files ON Messages.fid=Files.fid

结果如下:

mid bodytext fid path
1 Test 2 /files/2.png
2 Hi NULL NULL
3 Hello 3 /files/3.png

当我们需要输出所有消息记录时,无论是否有附加文件,我们都可以使用 LEFT JOIN,然后通过 PHP 来检测文件是否存在。

LEFT JOIN(不与右表交集的左连接)

LEFT JOIN 会输出左表中所有记录,除了 fid 在右表中有匹配的那些。

Messages 表:

mid bodytext fid
1 Test 2
2 Hi NULL
3 Hello 3

 Files 表:

fid path
1 /files/1.png
2 /files/2.png
3 /files/3.png

不与右表交集的 LEFT JOIN 查询如下:

SELECT * FROM Messages LEFT JOIN Files ON Messages.fid=Files.fid WHERE Files.fid IS NULL

结果如下:

mid bodytext fid path
2 Hi NULL NULL

这种 LEFT JOIN 用于输出所有没有附加文件的记录。

RIGHT JOIN(右连接)

RIGHT JOIN 输出右表中的所有记录,如果有匹配项,则显示来自左表的数据。

Messages 表:

mid bodytext fid
1 Test 2
2 Hi NULL
3 Hello 3

 Files 表:

fid path
1 /files/1.png
2 /files/2.png
3 /files/3.png

RIGHT JOIN 查询如下:

SELECT * FROM Messages RIGHT JOIN Files ON Messages.fid=Files.fid

结果如下:

mid bodytext fid path
NULL NULL 1 /files/1.png
1 Test 2 /files/2.png
3 Hello 3 /files/3.png

RIGHT JOIN 用于输出所有文件,不论它们是否被使用。

RIGHT JOIN(不与左表交集的右连接)

这种 RIGHT JOIN 输出右表中所有记录,除了那些与左表有交集的。

Messages 表:

mid bodytext fid
1 Test 2
2 Hi NULL
3 Hello 3

Files 表:

fid path
1 /files/1.png
2 /files/2.png
3 /files/3.png

查询如下:

SELECT * FROM Messages RIGHT JOIN Files ON Messages.fid=Files.fid WHERE Messages.fid IS NULL

结果如下:

mid bodytext fid path
NULL NULL 1 /files/1.png

这种 RIGHT JOIN 用于输出未附加到任何消息的文件,例如我们想找出未被使用的文件。

FULL OUTER JOIN(全外连接)

虽然 SQL 语言中有 FULL OUTER JOIN,但 MySQL 并不支持。这是因为这种操作符会对服务器造成较大负担。目前我们只有 3 个文件和 3 条消息,执行后会生成 4 行结果。虽然不建议,但我们可以用 LEFT JOIN 与 RIGHT JOIN 的并集(UNION)来模拟 FULL OUTER JOIN。

Messages 表:

mid bodytext fid
1 Test 2
2 Hi NULL
3 Hello 3

Files 表:

fid path
1 /files/1.png
2 /files/2.png
3 /files/3.png

FULL OUTER JOIN 的模拟查询如下:

SELECT * FROM Messages LEFT JOIN Files ON Messages.fid = Files.fid 
UNION 
SELECT * FROM Messages RIGHT JOIN Files ON Messages.fid = Files.fid

在该查询中,我们使用 UNION 将 LEFT JOIN 与 RIGHT JOIN 的结果合并。

结果如下:

mid bodytext fid path
1 Test 2 /files/2.png
2 Hi NULL NULL
3 Hello 3 /files/3.png
NULL NULL 1 /files/1.png

至于 FULL OUTER JOIN 的实际用途,虽然在 SQL 中存在,但在日常应用中并不常见。

FULL OUTER JOIN(不与任一表交集)

还有一种比 FULL OUTER JOIN 更极端的 JOIN 类型,即 FULL OUTER JOIN 不与任一表交集的版本。我几乎想不到在哪种情况下会使用这种 JOIN,因为结果包含未附加文件的消息与未被使用的文件。而且 MySQL 同样不支持 这种 JOIN,我们只能通过两个无交集的 LEFT JOIN 与 RIGHT JOIN 来模拟。

模拟查询如下:

$sql = 'SELECT * FROM Messages LEFT JOIN Files ON Messages.fid = Files.fid WHERE Files.fid IS NULL 
UNION 
SELECT * FROM Messages RIGHT JOIN Files ON Messages.fid = Files.fid WHERE Messages.fid IS NULL';

使用与上例相同的数据,我们将得到:

mid bodytext fid path
2 Hi NULL NULL
NULL NULL 1 /files/1.png

这大概就是全部内容了,在接下来的课程中,我们将开始编写更复杂的跨多表查询。