MySQL 筛选条件放 ON后 vs 放 WHERE 后的区别解析

 更新时间:2025年12月10日 11:59:16   作者:烟沙九洲  
文章解释了在MySQL中,将筛选条件放在ON和WHERE中的区别,文章通过几个场景说明了ON和WHERE的区别,并总结了ON用于关联,WHERE用于过滤,以及在LEFT JOIN中ON用于保行,在INNER JOIN中用于提效,本文介绍的非常详细,感兴趣的朋友跟随小编一起看看吧

今天我们来讲讲数据库筛选条件放 ON 后和放 WHERE 后的区别。

ON 决定如何 "连接" 表,WHERE 决定连接后 "显示" 哪些行。 这个根本区别导致了在 LEFT JOIN / RIGHT JOIN 外连接中,条件放置位置会产生巨大影响;而在 INNER JOIN 中,效果通常 等价

ON 条件匹配 被驱动表 的行,生成 "临时关联结果集"。LEFT JOIN 会保留 驱动表 所有行,匹配不上的 被驱动表 字段填充为 NULL

WHERE 会对 "临时关联结果集" 进行条件过滤,删除不满足的行。

接下来我们搞两张测试表,一目了然。

-- 用户表(驱动表,左表)
CREATE TABLE `ysjz_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO `ysjz_user` VALUES (1,'张三',18),(2,'李四',25),(3,'王五',30);
-- 订单表(被驱动表,右表)
CREATE TABLE `ysjz_order` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) DEFAULT NULL,
  `amount` decimal(10,2) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO `ysjz_order` VALUES (1,1,100),(2,2,200),(3,2,300),(4,4,500); -- 注:user_id=4无对应用户

场景一:使用 INNER JOIN,查询 年龄 > 20 的用户及其订单。

写法1:条件放 ON

SELECT u.*, o.* 
FROM `ysjz_user` u
INNER JOIN `ysjz_order` o ON u.id = o.user_id AND u.age > 20;

写法2:条件放 WHERE

SELECT u.*, o.* 
FROM `ysjz_user` u
INNER JOIN `ysjz_order` o ON u.id = o.user_id 
WHERE u.age > 20;

两种写法的 结果一致写法1 更高效,因少关联了 年龄 ≤ 20 的用户。

场景二:使用 LEFT JOIN保留所有用户,同时显示 年龄 > 20 的用户及其订单(≤ 20 的用户订单显示为 NULL)。

写法1:条件放 ON 后(符合要求)

SELECT u.*, o.* 
FROM `ysjz_user` u
LEFT JOIN `ysjz_order` o ON u.id = o.user_id AND u.age > 20;

写法2:条件放 WHERE 后(跟要求不符)

SELECT u.*, o.* 
FROM `ysjz_user` u
LEFT JOIN `ysjz_order` o ON u.id = o.user_id
WHERE u.age > 20;

写法2 将 张三 过滤了,并没有 保留所有用户。

场景三:使用 LEFT JOIN保留所有用户,同时显示 订单金额 > 200 的订单(无符合条件订单的用户填充为 NULL)。

写法1:条件放 ON 后(符合要求)

SELECT u.*, o.* 
FROM `ysjz_user` u
LEFT JOIN `ysjz_order` o ON u.id = o.user_id AND o.amount > 200;

写法2:条件放 WHERE 后(跟要求不符)

SELECT u.*, o.* 
FROM `ysjz_user` u
LEFT JOIN `ysjz_order` o ON u.id = o.user_id 
WHERE o.amount > 200;

写法2 过滤了 无符合条件订单的用户。

场景二 和 场景三 其实相差不大,只是条件作用的表不一样。

ON 后面优先放 "表之间的关联键"(如 u.id = o.user_id),非关联的筛选条件(如 u.age > 20)是否放 ON 后,取决于是否要保留驱动表的行。

总结:ON 管关联,WHERE 管过滤;LEFT JOIN 用 ON 保行,INNER JOIN 用 ON 提效

别人的嘴你堵不住,但自己的心却任由自己掌控。-- 烟沙九洲

到此这篇关于MySQL 筛选条件放 ON后 vs 放 WHERE 后的区别解析的文章就介绍到这了,更多相关mysql on where筛选内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • mysql 全文检索中文解决方法及实例代码

    mysql 全文检索中文解决方法及实例代码

    这篇文章主要介绍了mysql 全文检索中文解决方法及实例代码的相关资料,需要的朋友可以参考下
    2017-02-02
  • mysql 详解隔离级别操作过程(cmd)

    mysql 详解隔离级别操作过程(cmd)

    这篇文章主要介绍了mysql 详解隔离级别操作过程(cmd)的相关资料,需要的朋友可以参考下
    2017-01-01
  • MySQL 查询结果取交集的实现方法

    MySQL 查询结果取交集的实现方法

    本文将详细介绍MySQL中如何实现以SQL查询返回的结果集取交集的实现方法,需要的朋友可以参考
    2012-11-11
  • MySQL 8.0 可以操作 JSON 了

    MySQL 8.0 可以操作 JSON 了

    这篇文章主要介绍MySQL 8.0 如何操作 JSON ,经过漫长的测试,即将整体迁移至Mysql8.0; Mysql8.0 对于Json操作新增/优化了很多相关Json的API操作; 阅读了一下官方文档,虽然绝大多数的JSON操作都是应用层完成,下面来看文章的详细内容吧
    2021-10-10
  • mysql 增加修改字段类型及删除字段类型

    mysql 增加修改字段类型及删除字段类型

    本节主要介绍了mysql如何增加修改字段类型及删除字段类型,需要的朋友可以参考下
    2014-07-07
  • mysql修改数据库默认路径无法启动问题的解决

    mysql修改数据库默认路径无法启动问题的解决

    这篇文章主要给大家介绍了关于mysql修改数据库默认路径无法启动问题的解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-11-11
  • MySQL基于java实现备份表操作

    MySQL基于java实现备份表操作

    这篇文章主要介绍了MySQL基于java实现备份表操作,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-10-10
  • MySQL运算符使用方法全解析

    MySQL运算符使用方法全解析

    本文介绍了算数运算符、比较运算符、逻辑运算符和位运算符在MySQL中的使用方法和规则,结合实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧
    2025-12-12
  • MySQL模糊查询语句整理集合

    MySQL模糊查询语句整理集合

    在本篇文章里小编给大家分享的是一篇关于MySQL模糊查询语句整理内容,有兴趣的朋友们可以学习下。
    2020-02-02
  • 浅析MySQL实现数据迁移与备份恢复的详细指南

    浅析MySQL实现数据迁移与备份恢复的详细指南

    作为从 SQLServer 转向 MySQL 的运维人员,理解 MySQL 的数据迁移和恢复机制至关重要,下面将系统介绍 MySQL 的数据迁移技术、备份恢复策略以及底层存储原理,特别针对 Docker+Linux 环境下的运维实践
    2025-06-06

最新评论