根本区别在于数据保留逻辑:INNER JOIN只返回两表都匹配的行,LEFT JOIN强制保留左表全部行,右表无匹配时字段填NULL。

INNER JOIN 和 LEFT JOIN 的根本区别不在语法写法,而在数据保留逻辑:前者只返回两表都匹配的行,后者强制保留左表全部行。
INNER JOIN 只要“交集”,不匹配的行直接丢弃
当你用 INNER JOIN 连接两张表,数据库会逐行比对 ON 条件,只有两边都满足才进入结果集。哪怕左表某行在右表找不到对应记录,这行就彻底消失。
常见错误现象:SELECT * FROM users u INNER JOIN orders o ON u.id = o.user_id 查不到没下单的用户——这不是 bug,是设计如此。
- 性能通常更好:优化器更容易走索引,执行计划更简洁
- 不产生
NULL字段:结果里所有列都有值(前提是原表本身没NULL) - 等价写法多:
JOIN、INNER JOIN、甚至省略INNER都一样
LEFT JOIN 以左表为“锚点”,右表不匹配就填 NULL
LEFT JOIN 的核心承诺是:左表每一行都出现在结果里。右表有没有匹配项、匹配多少条,只影响右表字段是否为 NULL 或重复几遍,绝不影响左表行数。
典型误用:WHERE o.status = 1 放在 LEFT JOIN 后面,会把右表为 NULL 的行全过滤掉——实际效果等同于 INNER JOIN。
- 正确写法要把业务条件放进
ON:如ON u.id = o.user_id AND o.status = 1 - 结果中右表字段可能出现
NULL,后续WHERE或GROUP BY要注意空值处理 - 如果右表有重复匹配(一对多),左表行会被“撑开”,行数可能远超左表原始数量
ON 条件和 WHERE 条件在 LEFT JOIN 里不能互换
这是最容易踩坑的地方。对 LEFT JOIN 来说,ON 决定“怎么连”,WHERE 决定“最后留哪些行”。
示例对比:
SELECT u.name, o.order_no FROM users u LEFT JOIN orders o ON u.id = o.user_id AND o.status = 1;
→ 所有用户都在,只连状态为 1 的订单,没匹配则 o.order_no 为 NULL。
SELECT u.name, o.order_no FROM users u LEFT JOIN orders o ON u.id = o.user_id WHERE o.status = 1;
→ 实际过滤掉了所有 o.status 不为 1 的行,包括 o.status 是 NULL 的行(即没订单的用户),结果只剩有状态 1 订单的用户。
-
ON中的非关联条件(如o.status = 1)只作用于右表筛选,不影响左表存在性 -
WHERE对整个临时结果集生效,NULL值参与比较时永远为 false - 想查“所有用户 + 其有效订单”,必须把
status放ON;想查“有有效订单的用户”,用INNER JOIN更直白
什么时候该选 INNER JOIN,什么时候必须用 LEFT JOIN
别凭感觉,看业务语义:
- 要“同时存在”的数据(如订单及其客户信息),用
INNER JOIN - 要“主表完整 + 关联可选”的数据(如用户列表 + 他们的最新订单号),必须用
LEFT JOIN - 涉及统计类查询(如每个用户的订单总数),
LEFT JOIN+COUNT(o.id)才能区分“0 单”和“无数据” - 嵌套子查询或多次
JOIN时,混用两者容易让逻辑失控,建议先明确每一步的数据边界
真正难的不是语法,而是判断哪张表是“事实主体”——它决定了你该用哪个 JOIN 作为起点。一旦主表选错,后面所有条件都可能跑偏。


















