首页/数据/SQL 速查/INNER JOIN 内连接基础

INNER JOIN 内连接基础

按连接条件把两张表的行配对,只保留匹配成功的组合;显式 JOIN 语法比逗号连接更清晰,也不容易漏写连接条件。

SQL 速查数据更新于 2026-10-13

INNER JOIN 是什么

INNER JOIN 按连接条件把两张表的行配对,只保留两边都匹配成功的组合,任何一边没有匹配的行都会从结果里消失。显式写 JOIN … ON 比逗号加 WHERE 的隐式连接更清晰,也不容易在多加一张表时漏写连接条件而变成笛卡尔积。连接在存储引擎层的实现通常是嵌套循环或哈希匹配,被驱动表的连接列上有索引能大幅降低代价。多表连接时优化器自行决定驱动顺序,一般倾向把小结果集作为驱动表。

基本信息

作用按条件配对两表行,只保留匹配成功的组合
语法SELECT … FROM a INNER JOIN b ON a.id = b.a_id
等价写法INNER 可省略;逗号加 WHERE 是老式隐式连接
连接条件等值与不等值(>、<、BETWEEN)都可以写在 ON
连接键类型两侧类型与字符集建议一致,否则索引可能失效
输出顺序不保证,需要顺序要显式 ORDER BY

典型使用场景

  • 取明细与主表信息:订单连用户拿到下单人姓名
  • 多表串联取完整视图:商品连类目再连品牌
  • 用连接代替子查询:IN 子查询改写为 INNER JOIN 通常更高效
  • 维度关联:事实表连日期维表、地区维表出报表
  • 数据校验:内连接找出两边都存在但对不上的记录
  • 自连接:员工表连自身找上级,或找出同城用户配对

多表连接示例

多表连接示例
SELECT o.id, o.amount, u.name AS user_name, p.title
FROM orders AS o                              # 过滤后的小结果集作驱动表
JOIN order_items AS i ON i.order_id = o.id    # 一对多,会放大行数
JOIN products AS p ON p.id = i.product_id     # 继续串联
WHERE o.status = 'paid'                       # 内连接里 WHERE 与 ON 等价
  AND o.created_at >= '2024-01-01'
ORDER BY o.id;

隐式连接与笛卡尔积

隐式连接与笛卡尔积
-- 老式隐式连接,不推荐
SELECT o.id, u.name FROM orders o, users u WHERE o.user_id = u.id;

-- 漏写连接条件就是笛卡尔积,行数是两表行数相乘
SELECT COUNT(*) FROM orders o JOIN users u;   # 危险,结果集爆炸

-- 确实需要全集时显式写 CROSS JOIN,说明这是有意为之
SELECT * FROM sizes CROSS JOIN colors;

连接类型对照

类型保留哪些行典型用途
INNER JOIN两边都匹配的行常规取数
LEFT JOIN左表全部加匹配的右表主表带可选信息
RIGHT JOIN右表全部加匹配的左表可改写成调换顺序的 LEFT JOIN
FULL JOIN两边全部,缺的补 NULLMySQL 不支持,需用 UNION 模拟
CROSS JOIN两表笛卡尔积生成组合集合
内连接里 ON 与 WHERE 可互换;一旦换成外连接,写在 WHERE 的右表条件会把补 NULL 的行过滤掉,语义立刻改变。
连接键两侧类型不一致(如 bigint 对 varchar)会触发隐式转换,被驱动表索引可能失效,EXPLAIN 里会看到 type=ALL。
一对多连接一定会放大结果行数,统计金额前先确认口径:按订单统计要先把明细聚合到订单粒度再连接。
多表连接时漏写其中一个 ON 条件不会报错,只会悄悄产生笛卡尔积,排查时先看结果行数是否异常增大。

连接优化要点

  • 驱动表选过滤后行数小的那张:先用 WHERE 把结果集缩小,再参与连接
  • 被驱动表的连接列要有索引:没有索引会退化成逐行全表扫描
  • 连接键的类型与字符集保持一致:隐式转换会让索引失效
  • 先聚合再连接:明细表按关联键聚合到一行后连接,避免行数放大
  • 少用 SELECT *:连接后同名列容易冲突,显式列清单也更少读数据
  • 多表连接的顺序看 EXPLAIN:通常第一行是驱动表,MySQL 可用 STRAIGHT_JOIN 指定顺序
  • 连接列上有函数或表达式时索引失效,把计算移到常量一侧
连接列建议加 NOT NULL 约束,并在建表时统一两侧的字符集与排序规则,能避免大量隐式转换导致的索引失效。

易错点

  • 漏写一张表的连接条件,产生笛卡尔积,行数爆炸且不报错
  • 连接键两侧类型或字符集不一致,索引失效退化为全表扫描
  • 一对多连接后直接 SUM,金额或数量被重复累计
  • 把该用外连接的场景写成内连接,导致左表未匹配的行整体消失
  • 在 ON 里写只属于左表的过滤条件,语义不清且容易被后续维护者改动出问题

数据来源与参考

  • MySQL 8.0 Reference Manual · JOIN Clause
  • PostgreSQL Documentation · Joined Tables
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌