SQL INNER JOIN:仅保留两表匹配行

在 SQL 中,INNER JOIN 只返回两张表都满足连接条件的行。它适合合并关联数据,例如把业务记录关联到字典表值,并在结果中排除没有匹配项的行。由于连接谓词要求两侧同时成立,连接键为 NULL 或没有对应匹配的记录都会被自动过滤。

SQL INNER JOIN 关联表数据示例

输出:

输出将显示在这里...

输出:

+----------+--------------+
| employee | department   |
+----------+--------------+
| 阿尔玛   | 工程部       |
| 本       | 工程部       |
| 卡拉     | 销售部       |
+----------+--------------+
3 row(s)

这个示例如何工作

  1. departments 有三个部门;employees 有四位员工,每人带一个外键 dept_id。丹的 dept_id 是 NULL。
  2. INNER JOIN departments d ON d.id = e.dept_id 会把每位员工与 id 等于其 dept_id 的部门行配对。只有两侧都匹配的配对会被保留。
  3. 丹的 dept_id = NULL。当任一操作数为 NULL 时,= 运算结果是 unknown,所以丹不会匹配任何部门并被排除。
  4. 人力资源部(id 3)没有任何员工指向它,因此也不会出现在结果中。INNER JOIN 会丢弃两侧未匹配的行。

什么是 SQL INNER JOIN?

INNER JOIN 根据连接谓词返回两张表的交集。从逻辑上看,它只保留 ON 条件为 true 的行对。具体物理执行会随数据库引擎和数据分布变化(嵌套循环、哈希连接、归并连接),但结果集始终只包含匹配行。

INNER JOIN 与 LEFT JOIN

INNER JOINLEFT JOIN
只返回两张表都匹配的行返回左表全部行,右表无匹配时填充 NULL
未匹配行会被静默丢弃左表未匹配行会保留,右侧列为 NULL
适用于缺少匹配即代表数据无效的场景适用于无论是否匹配都要保留左表记录的场景

规则:当结果中的每一行都必须同时拥有两张表的有效数据时,用 INNER JOIN。若需要即使右侧无匹配也保留左侧行,改用 LEFT JOIN。

SQL INNER JOIN 的常见错误

遗漏连接条件或使用恒为 true 的条件

省略 ON 子句(或写出恒为 true 的条件)会产生笛卡尔积:每位员工都会与每个部门配对。

-- 错误:笛卡尔积(4 × 3 共 12 行)
SELECT * FROM employees, departments;

-- 正确:显式连接条件
SELECT * FROM employees e
INNER JOIN departments d ON d.id = e.dept_id;

连接键不唯一导致行倍增

INNER JOIN 会为每一对匹配生成一行结果。如果连接到的表上连接键并不唯一,左侧一行可能匹配右侧多行,从而把结果放大。

INNER JOIN 与 EXISTS

当结果需要两张表的列时,用 INNER JOIN。若你只想按“是否存在关联行”来筛选,优先用 EXISTS。若子查询可能匹配多行,EXISTS 还能避免行倍增,而且查询优化器通常可在找到第一条匹配后停止。

-- EXISTS:每位有匹配部门的员工只返回一行
SELECT e.name FROM employees e
WHERE EXISTS (SELECT 1 FROM departments d WHERE d.id = e.dept_id);

性能说明

为连接谓词中的列建立索引(本例是 dept_iddepartments.id)。没有索引时,数据库可能反复扫描内表。面对大表时,用 EXPLAIN QUERY PLAN 检查执行计划,优先看到 USING INDEXSEARCH,而不是 SCAN