SQL INNER JOIN:仅保留两表匹配行
在 SQL 中,INNER JOIN 只返回两张表都满足连接条件的行。它适合合并关联数据,例如把业务记录关联到字典表值,并在结果中排除没有匹配项的行。由于连接谓词要求两侧同时成立,连接键为 NULL 或没有对应匹配的记录都会被自动过滤。
SQL INNER JOIN 关联表数据示例
输出:
输出将显示在这里...
输出:
+----------+--------------+
| employee | department |
+----------+--------------+
| 阿尔玛 | 工程部 |
| 本 | 工程部 |
| 卡拉 | 销售部 |
+----------+--------------+
3 row(s)
这个示例如何工作
departments有三个部门;employees有四位员工,每人带一个外键dept_id。丹的dept_id是 NULL。INNER JOIN departments d ON d.id = e.dept_id会把每位员工与id等于其dept_id的部门行配对。只有两侧都匹配的配对会被保留。- 丹的
dept_id = NULL。当任一操作数为 NULL 时,=运算结果是 unknown,所以丹不会匹配任何部门并被排除。 - 人力资源部(id 3)没有任何员工指向它,因此也不会出现在结果中。INNER JOIN 会丢弃两侧未匹配的行。
什么是 SQL INNER JOIN?
INNER JOIN 根据连接谓词返回两张表的交集。从逻辑上看,它只保留 ON 条件为 true 的行对。具体物理执行会随数据库引擎和数据分布变化(嵌套循环、哈希连接、归并连接),但结果集始终只包含匹配行。
INNER JOIN 与 LEFT JOIN
| INNER JOIN | LEFT 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_id 与 departments.id)。没有索引时,数据库可能反复扫描内表。面对大表时,用 EXPLAIN QUERY PLAN 检查执行计划,优先看到 USING INDEX 或 SEARCH,而不是 SCAN。