解析mysql left( right ) join使用on与where筛选的差异

有这样的一个问题mysql查询使用mysql中left(right)join筛选条件在on与where查询出的数据是否有差异。
可能只看着两个关键字看不出任何的问题。那我们使用实际的例子来说到底有没有差异。

例如存在两张表结构
表结构1


代码如下:

drop table if EXISTS A; 
CREATE TABLE A ( 
  ID int(1) NOT NULL, 
  PRIMARY KEY  (ID) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

表结构2


代码如下:

drop table if EXISTS B; 
CREATE TABLE B ( 
  ID int(1) NOT NULL, 
  PRIMARY KEY  (ID) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

表一插入数据


代码如下:

insert into A values ( 1 ); 
insert into A values ( 2 ); 
insert into A values ( 3 ); 
insert into A values ( 4 ); 
insert into A values ( 5 ); 
insert into A values ( 6 );

表二插入数据


代码如下:

insert into B values ( 1 ); 
insert into B values ( 2 ); 
insert into B values ( 3 );

完成后A,B表数据如下:


语句一


代码如下:

select  A.ID as AID, B.ID as BID   from A left join B on A.ID = B.ID where B.ID<3

语句二


代码如下:

select  A.ID as AID, B.ID as BID  from A left join B on A.ID = B.ID and  B.ID<3

以上两个语句的查询结果是否一致。
反正一切我是没有注意到这两个查询存在任何差异的【以前也没这么写过sql】。
我们看看实际结果
语句一的查询结果

语句二的查询结果为:

发现两个查询存在差异。

为什么会存在差异,这和on与where查询顺序有关。

我们知道标准查询关键字执行顺序为 from->where->group by->having->order by[ 记得不是很清楚呢]

left join 是在from范围类所以 先on条件筛选表,然后两表再做left join。

而对于where来说在left join结果再次筛选。

第一sql语句查询过程如下等价于:
1:先是left join


代码如下:

select  A.ID as AID, B.ID as BID   from A left join B on A.ID = B.ID

查询结果如下

2:再查询结果中将B.ID即BID<2筛选出来。

也就是我们上面看到的结果。

第二sql语句查询过程如下等价于:

1:先按照on条件刷选表等价于先筛选B表:

2:再已上查询结果与A表做left join,这也是为什么我们看到第二个查询的sql会保留A表的原因。
ON与where的使用一定要注意场所:
(1):ON后面的筛选条件主要是针对的是关联表【而对于主表刷选条件不适用】。
例如


代码如下:

select  A.ID as AID, B.ID as BID from A left join B on A.ID = B.ID and A.ID = 3

这个的查询结果为

挺诧异的吧和我们期望的结果不一样,并为筛选出AID=3的数据。

但是我们也发现 AID 与 中AID 1 于2对应的值为NULL,关联表只取了满足A表筛刷选条件的值。

即主表条件在on后面时附表只取满足主表帅选条件的值、而主表还是取整表。

(2):对于主表的筛选条件应放在where后面,不应该放在ON后面

(3):对于关联表我们要区分对待。如果是要条件查询后才连接应该把查询件

              放置于ON后。

              如果是想再连接完毕后才筛选就应把条件放置于where后面

(4): 对于关联表我们其实可以先做子查询再做join
所以第二个sql等价于


代码如下:

select  A.ID as AID, B1.ID as BID 
from A left join  ( select B.ID from B  where B.ID <3 )B1 on A.ID = B1.ID

以上全在mysql5.1上测试过

(0)

相关推荐

  • SQL where条件和jion on条件的详解及区别

    sql 语句中where条件和jion on条件的区别 与有很大的差别,请注意! SELECT TBL_SchemaDetail.MaterialNo, TBL_StockMaterial.SalePrice FROM TBL_StockMaterial RIGHT OUTER JOIN TBL_SchemaDetail ON TBL_StockMaterial.MaterialNo = TBL_SchemaDetail.MaterialNo AND TBL_SchemaDetail.Schem

  • 解析sql语句中left_join、inner_join中的on与where的区别

    table a(id, type):id     type ----------------------------------1      1         2      1          3      2          table b(id, class):id    class ---------------------------------1      12      2sql语句1:select a.*, b.* from a left join b on a.id = b

  • sql连接查询语句中on、where筛选的区别总结

    前言 相信对于每位程序员来说,sql查询这个东西, 要说它简单, 可以很简单, 通常情况下只需使用增删查改配合编程语言的逻辑表达能力,就能实现所有功能. 但是增删查改并不能代表sql语句的所有, 完整的sql功能会另人望而生畏. 就拿比普通增删查改稍微复杂一个层次的连接查询来说, 盲目使用, 也会出现意料之外的危险结果,导致程序出现莫名其妙的BUG. 在连接查询语法中,另人迷惑首当其冲的就要属on筛选和where筛选的区别了, 在我们编写查询的时候, 筛选条件的放置不管是在on后面还是where

  • 解析mysql left( right ) join使用on与where筛选的差异

    有这样的一个问题mysql查询使用mysql中left(right)join筛选条件在on与where查询出的数据是否有差异.可能只看着两个关键字看不出任何的问题.那我们使用实际的例子来说到底有没有差异. 例如存在两张表结构表结构1 复制代码 代码如下: drop table if EXISTS A;  CREATE TABLE A (    ID int(1) NOT NULL,    PRIMARY KEY  (ID)  ) ENGINE=MyISAM DEFAULT CHARSET=lat

  • 解析MySQL join查询的原理

    MySQL用Nested-Loop Join算法实现join查询 区分驱动表和被驱动表,以驱动表的结果集为循环的基础,访问被驱动表过滤数据,然后合并结果,驱动表在外循环.被驱动表在内循环.如果还有第三张参与join查询的表,则以合并的结果为驱动表,第三张表作为被驱动表,以此类推. left join中的左表是驱动表.右表是被驱动表,right join刚好相反. Nested-Loop Join有三种实现 SNLJ Simple Nested-Loop Join 假设A是驱动表,B是被驱动表.

  • 解析MySQL中存储时间日期类型的选择问题

    一般应用中,我们用timestamp,datetime,int类型来存储时间格式: int(对应javaBean中的Integer或int) 1. 占用4个字节 2. 建立索引之后,查询速度快 3. 条件范围搜索可以使用使用between 4. 不能使用mysql提供的时间函数 结论:适合需要进行大量时间范围查询的数据表 datetime(javaBean中用Date类型) 1. 占用8个字节 2. 允许为空值,可以自定义值,系统不会自动修改其值. 3. 实际格式储存(Just stores w

  • 深入解析MySQL索引的原理与优化策略

    目录 索引的概念 索引的原理 索引的类型 索引的使用 索引的使用方式 注意事项 索引优化技巧 索引的概念 MySQL索引是一种用于加速数据库查询的数据结构,它类似于书籍的目录,能够快速指导我们找到需要的信息.MySQL索引可以根据一定的算法和数据结构进行排序和存储,从而实现高效的数据查找和访问.在数据库中,索引可以加速数据的查询和更新操作,提高系统性能. MySQL支持多种索引类型,常见的包括B-tree索引.哈希索引和全文索引等.其中,B-tree索引是最常用的一种,它是一种平衡树结构,可以将

  • 在MySQL中使用JOIN语句进行连接操作的详细教程

    到目前,我们已经学习了从一个表中获取数据.这是简单的需要,但在大多数现实MySQL的使用,经常需要将数据从多个表中的一个单一的查询. 可以使用多个表中的单一SQL查询.在MySQL中联接(join)行为是指两个或多个表到一个表中可以使用连接在SELECT,UPDATE和DELETE语句中加入MySQL表.我们将看到一个例子LEFT JOIN简单的MySQL连接. 在命令提示符使用联接: 假设我们两个表的教程tcount_tbl和tutorials_tbl的完整列表如下: 例子: 试试下面的例子:

  • 深度解析MySQL启动时报“The server quit without updating PID file”错误的原因

    很多童鞋在启动mysql的时候,碰到过这个错误, 首先,澄清一点,出现这个错误的前提是:通过服务脚本来启动mysql.通过mysqld_safe或mysqld启动mysql实例并不会报这个错误. 那么,出现这个错误的原因具体是什么呢? 哈哈,对分析过程不care的童鞋可直接跳到文末的总结部分~ 总结 下面,来分析下mysql的服务启动脚本 脚本完整内容如下: #!/bin/sh # Copyright Abandoned 1996 TCX DataKonsult AB & Monty Progr

  • MySQL表LEFT JOIN左连接与RIGHT JOIN右连接的实例教程

    LEFT JOIN 语法用法与实例 MySQL LEFT JOIN 语法 SQL(MySQL) LEFT JOIN 会取得左表(table1)全部记录,即使右表(table2)并无对应匹配记录.LEFT JOIN 基本语法如下: ... FROM table1 LEFT JOIN table2 ON condition ... MySQL LEFT JOIN 用法实例 下面是两个原始数据表: article 文章表: user 用户表: 我们列出所有的文章及对应的所属用户,即使没有用户的文章也列

  • mysql中left join设置条件在on与where时的用法区别分析

    本文实例讲述了mysql中left join设置条件在on与where时的用法区别.分享给大家供大家参考,具体如下: 一.首先我们准备两张表来进行测试. CREATE TABLE `a` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID', `name` varchar(32) DEFAULT '' COMMENT '名称', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET

  • 全面解析MySQL中的隔离级别

    数据库并发的对同一批数据进行增删改,就可能会出现我们所说的脏写.脏读.不可重复读.幻读等一系列问题.MySQL提供了一系列机制来解决事务并发问题,比如事务隔离.锁机制.MVCC多版本并发控制机制.今天来探究一下事务隔离机制. 事务是一组SQL组成的逻辑处理单元,先来看下事务的ACID特性: 原子性(Atomicity) :事务是一个原子操作单元,对数据进行修改,要么全执行要么全不执行.是从执行层面上来描述的. 一致性(Consistent) :在事务开始和完成时,数据都必须保持一致状态.是从执行

  • 详解mysql 使用left join添加where条件的问题分析

    当前需求: 有group和factor两张表,一个group对应多个factor,现在想查询有效的group和对应的有效的factor,两个表都有isDel逻辑删除标志. 最开始的错误写法一: SELECT g.*,f.* FROM groups g LEFT JOIN factor f ON f.groupId = g.id where g.isDel=0 and f.isDel=0 LEFT JOIN 关键字会从左表 (table_name1) 那里返回所有的行,即使在右表 (table_n

随机推荐