ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

left join 和inner join on 后边的条件 还有 and 条件 和where 后的比较

2026/8/4 4:57:39 拓冰建站 浏览量
left join 和inner join on 后边的条件 还有 and 条件 和where 后的比较

在 SQL 中,LEFT JOININNER JOIN后面跟上ON条件、AND条件以及WHERE条件,它们的行为逻辑有着本质的区别。理解这个区别是写出无 Bug SQL 的关键。

核心一句话总结:ON决定“如何连接”,WHERE决定“要哪些行”。对于LEFT JOINON中的条件永远不丢弃左表数据;而WHERE中的条件会。

下面我分两种连接类型,为你彻底拆解:


1. 对于 INNER JOIN:两者逻辑等价(但推荐写 ON)

INNER JOIN(内连接)中,无论是把条件写在ON后面、AND后面,还是WHERE后面,最终结果和性能执行计划几乎完全一样

sql

-- 这三种写法结果完全一致 SELECT * FROM A INNER JOIN B ON A.id = B.id AND B.status = 1; SELECT * FROM A INNER JOIN B ON A.id = B.id WHERE B.status = 1; SELECT * FROM A INNER JOIN B ON A.id = B.id AND A.age > 18 WHERE B.status = 1;
  • 原因:INNER JOIN 只取两表的交集,任何一方不满足条件,整行都会被丢弃。

  • 最佳实践:虽然位置不影响结果,但为了可读性维护性,强烈建议:

    • ON后面只放表与表之间的关联条件(如A.id = B.id)。

    • WHERE后面放业务过滤条件(如B.status = 1)。

    • 这样代码逻辑清晰,一眼能看出什么是连接关系,什么是业务筛选。


2. 对于 LEFT JOIN:这是本质区别(极易踩坑)

LEFT JOIN以左表为准,无论如何,左表的数据都会全部返回。此时,ON/ANDWHERE产生了分水岭般的作用。

场景 A:条件放在ONAND中(不影响左表行数)

这里的条件(非关联条件)是在生成临时结果集之前,专门用于过滤右表的。

  • 效果:左表数据全部保留,右表只有满足AND条件的行被连接上;如果不满足,右表字段填NULL

  • 示例

sql

-- 需求:查出所有用户,并尝试查出他们状态为 1 的订单 SELECT u.id, u.name, o.order_no FROM users u LEFT JOIN orders o ON u.id = o.user_id AND o.status = 1;

结果:张三(无订单)会返回NULL;李四(有订单但状态=0)会返回NULL;王五(有订单且状态=1)显示订单号。左表用户一条都不会少

场景 B:条件放在WHERE中(可能把 LEFT JOIN 变成 INNER JOIN)

这里的条件是在临时结果集生成之后,对整体结果进行最终过滤

  • 效果:只要右表的字段不满足WHERE条件,并且右表字段为NULL,那么这一整行(包括左表数据)都会被彻底丢弃

  • 示例

sql

-- 需求:查出所有用户,并且只要状态为 1 的订单(错误写法,会丢用户) SELECT u.id, u.name, o.order_no FROM users u LEFT JOIN orders o ON u.id = o.user_id WHERE o.status = 1;

结果:张三(无订单,o.status IS NULL)因为不满足WHERE o.status = 1,整行被丢弃,导致查不到没有符合条件的订单的用户。这实际上等效于INNER JOIN


3. 执行顺序与性能影响(数据库视角)

SQL 标准的逻辑执行顺序为:FROMONJOINWHERESELECT

  1. ON阶段(含 AND):发生在连接过程中。数据库会根据ON条件,决定如何从右表匹配数据。对于LEFT JOIN,右表数据在此时就被筛选掉了,这能减少参与连接的数据量,提升性能。

  2. WHERE阶段:发生在连接完成后。此时数据行已经确定,WHERE是对最终结果集的“清洗”。

性能陷阱警告:如果你在LEFT JOINWHERE中过滤了右表的非空字段,数据库优化器会识别出“右表不能为 NULL”,从而自动将LEFT JOIN重写为INNER JOIN。虽然执行计划可能变快,但业务逻辑完全变了(数据丢了),这是最致命的隐藏 Bug。


4. 终极实战建议(记住这张表)

你的业务需求条件应该写在哪为什么
表与表的关联键(如A.id = B.a_id写在ON后面这是连接的基本契约,必须放这里。
针对“右表”的限制条件(且必须保留左表全部数据写在ON后面(用AND例如:LEFT JOIN B ON A.id=B.id AND B.type=1,确保左表不丢失。
针对“左表”的限制条件(如只要姓张的用户)写在WHERE后面例如:WHERE A.name LIKE '张%',因为左表为空时应该丢弃该用户。
针对“右表”的限制条件(且不需要左表的空数据)直接改用INNER JOIN,写在ONWHERE均可既然左表空数据不要了,用INNER JOIN语义更清晰,性能也更好。
通用的业务硬性过滤(如时间范围、状态码)写在WHERE后面这是对最终返回结果的统一筛选,维护起来最直观。

终极口诀

关联条件上ON,过滤右表加AND,过滤整体放WHERE,左表数据想保全,右表过滤别放WHERE