INNER JOIN只返回两表联结字段值完全相等的记录,不满足条件的行全被过滤;LEFT JOIN保留左表全部行,右表无匹配则补NULL;RIGHT JOIN极少使用,可转为LEFT JOIN;MySQL不支持FULL OUTER JOIN,需用UNION模拟。

INNER JOIN 只返回匹配的行,不满足条件的数据全被过滤
这是最常用的连接方式,INNER JOIN(或简写为 JON)只保留左表和右表中联结字段值完全相等的记录。一旦某行在任一表中找不到对应匹配,它就不会出现在结果里。
常见错误是误以为它会补空值或保留主表全部数据——其实不会。比如用 users 表关联 orders 表时,没下过单的用户根本不会出现。
- 等价写法:
JOIN和INNER JOIN完全相同,MySQL 中无区别 - 性能上通常最优,因优化器可尽早剪枝
- 若联结字段有
NULL,这些行一定不会被包含(NULL = NULL为FALSE)
LEFT JOIN 保留左表全部行,右表无匹配则补 NULL
LEFT JOIN 的关键在于“左表驱动”:无论右表有没有匹配,左表每一行都至少出现一次。没匹配上的右表字段全为 NULL。
典型场景是查“所有用户及其最新订单”,即使部分用户没订单也要列出来。但要注意:如果在 WHERE 子句里对右表字段加非空限制(如 WHERE o.status = 'paid'),就可能把本该保留的左表空匹配行给筛掉——这实际退化成了 INNER JOIN。
- 正确写法:把右表的过滤条件放到
ON子句里,例如ON u.id = o.user_id AND o.status = 'paid' - 错误写法:
LEFT JOIN ... ON u.id = o.user_id WHERE o.status = 'paid'→ 丢失无订单用户 - 索引建议:左表联结字段最好有索引;右表若常用于
ON后的附加条件,相关字段也应考虑联合索引
RIGHT JOIN 很少用,逻辑上可统一转成 LEFT JOIN
RIGHT JOIN 是以右表为基准保留全部行,左表无匹配则补 NULL。但它和 LEFT JOIN 本质对称,只是左右调换。几乎所有情况都能通过交换表顺序 + 改用 LEFT JOIN 实现,可读性和维护性更好。
MySQL 手册明确建议避免使用 RIGHT JOIN,尤其在多表连接中容易绕晕自己。团队代码规范里基本禁止它。
- 等价转换:
A RIGHT JOIN B ON A.x = B.y⇔B LEFT JOIN A ON A.x = B.y - 执行计划几乎一致,无性能差异
- 嵌套多个
RIGHT JOIN时,阅读顺序与执行顺序反直觉,极易出错
FULL OUTER JOIN 在 MySQL 中不存在,需用 UNION 模拟
MySQL 原生不支持 FULL OUTER JOIN。它的语义是“左右表所有行都保留,各自无匹配的部分用 NULL 填充”。要实现类似效果,必须组合 LEFT JOIN + RIGHT JOIN + UNION。
SELECT u.id, u.name, o.order_id FROM users u LEFT JOIN orders o ON u.id = o.user_id UNION ALL SELECT u.id, u.name, o.order_id FROM users u RIGHT JOIN orders o ON u.id = o.user_id WHERE u.id IS NULL;
注意这不是严格等价:上面写法会重复出现双方都有匹配的行(即 INNER JOIN 部分)。真正严谨的做法要用 UNION(去重)并拆成三部分:LEFT JOIN(含右表 NULL)、RIGHT JOIN(含左表 NULL)、再排除交集。但实际业务中极少需要这么复杂,多数时候用两个 LEFT JOIN 分别查再合并更清晰。
真正容易被忽略的是 NULL 处理:所有 JOIN 类型中,只要字段来自未匹配侧,值就是 NULL,不是空字符串或 0。做聚合或判断前必须显式用 IS NULL 或 COALESCE() 处理,否则结果可能不符合预期。










