SQL在JOIN语句中过滤条件写在哪_WHERE与ON条件执行效率对比

1次阅读

ON 在 JOIN 过程中决定匹配行,WHERE 在 JOIN 后筛选结果;LEFT JOIN 中右表条件放 ON 保留左表行、放 WHERE 则退化为 INNER JOIN;INNER JOIN 下二者通常等效但不可依赖;务必用 EXPLAIN 验证执行计划。

SQL 在 JOIN 语句中过滤条件写在哪_WHERE 与 ON 条件执行效率对比

WHERE 和 ON 的执行时机完全不同

JOIN 之后再 WHERE 过滤,和把条件写进 ON 里,看起来结果一样,实际执行计划、数据量、索引使用都可能差很远。核心区别在于:ON 是在 JOIN 过程中决定“哪些行能匹配上”,而 WHERE 是在 JOIN 完成后对整张结果表做筛选。

LEFT JOIN 中 ON 后加条件 ≠ WHERE 后加条件

这是最容易出错的场景。如果在 LEFT JOIN …… ON 里加右表的过滤条件(比如 ON b.status = 'active'),没匹配上的左表行仍会保留,右表字段为 NULL;但若写成 LEFT JOIN …… ON …… WHERE b.status = 'active',就会把所有右表不满足的行(包括 NULL 行)全干掉,LEFT JOIN 变相退化成 INNER JOIN。

  • LEFT JOIN b ON a.id = b.a_id AND b.status = 'active' → 保留所有 a 行,b 不满足时 b.* 全为 NULL
  • LEFT JOIN b ON a.id = b.a_id WHERE b.status = 'active' → 实际只留 a 和 b 都有且 b.status 匹配的行
  • 用 EXPLAIN 看执行计划,后者常出现 Using where 且 rows 显著变少,说明过滤发生在 JOIN 后,已丢失左表冗余信息

INNER JOIN 下 ON 和 WHERE 效果通常一致,但别依赖优化器

理论上,INNER JOINONWHERE 的等价条件会被优化器合并处理,执行计划往往一样。但实际中不能假设一定如此:

  • 多个 JOIN 时,条件位置会影响驱动表选择 —— 把过滤强的条件尽量放在对应表的 ON 子句里,有助于优化器提前剪枝
  • 含函数或类型转换的条件(如 WHERE UPPER(b.name) = 'ABC')放 WHERE 更安全,放 ON 可能干扰索引下推
  • 某些旧版 MySQL(5.6 以前)或复杂嵌套查询中,WHERE 条件延迟应用会导致临时表膨胀

用 EXPLAIN 验证,别猜执行逻辑

有没有真正走索引、是否用了临时表、rows 扫描量多少——这些全得靠 EXPLAIN 看,而不是看 SQL 写得“顺不顺眼”。尤其当表数据量上百万后,ONWHERE 差一个条件,执行时间可能从 0.02s 涨到 12s。

  • 重点关注 type(最好为 refrange)、key(是否命中索引)、rows(预估扫描行数)
  • 对比两个版本的 EXPLAIN 输出,哪怕只是把 WHERE b.x = 1 挪到 ON 里,rows 可能从 500000 降到 300
  • 注意 Extra 字段:出现 Using join bufferUsing temporary 就是危险信号

真实业务里,JOIN 条件的位置不是语法风格问题,是数据流控制问题。ON 是建表关系时就该想清楚的约束,WHERE 是最终呈现前的裁剪。两者混用,等于一边搭桥一边拆砖。

星耀云
版权声明:本站原创文章,由 星耀云 2026-03-21发表,共计1229字。
转载说明:转载本网站任何内容,请按照转载方式正确书写本站原文地址。本站提供的一切软件、教程和内容信息仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。
text=ZqhQzanResources