`

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上测试过

 

 

 

  • 大小: 17.5 KB
  • 大小: 15.7 KB
  • 大小: 19.1 KB
  • 大小: 19.7 KB
  • 大小: 9 KB
  • 大小: 20.8 KB
7
1
分享到:
评论
4 楼 greatwqs 2014-04-08  
写得不错, 采用最后一种的SQL写法确实存在很多问题, 子查询数据太多.
执行效率很慢, 如果整个SQL的返回数据较多, 我用的时候还在前面加了一个insert, 经常造成MySQL死锁.
3楼第二个SQL
select * from bt left join  ( select bt1.ID from bt1  where bt1.`VName`<'M5' and bt1.ID <1000 )B1 on bt.ID = b1.`ID`
where bt.ID <1000

执行时间少, 应该是子查询结果集比较小的原因,
如果较大还是用 LEFT JOIN XXXX ON .. AND ..
3 楼 80197675 2011-01-18  
xiangzi21 写道
写的不错!
不过最后一个例子
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

如果数据量小倒是可以,如果数据量大了mysql对关联字查询的效率不高吧?

刚才看呢下 上个是我子查询的sql写的有问题
select * from bt left join  ( select bt1.ID from bt1  where bt1.`VName`<'M5' and bt1.ID <1000 )B1 on bt.ID = b1.`ID`
where bt.ID <1000

如果修改成上面的
查询时间为 105ms
和查询二相差不了多少。

所以应该效率是差不多......
即子查询与之间on查询效率应该差不了多少,单子查询必须写正确,像我第一次写的子查询就没写正确。

下次等测试完毕再下结论 呵呵

2 楼 80197675 2011-01-18  
xiangzi21 写道
写的不错!
不过最后一个例子
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

如果数据量小倒是可以,如果数据量大了mysql对关联字查询的效率不高吧?

恩 谢谢提醒。
会存在这样的问题,并且对于非索引列效率相差太大。

我拿这两张表做实验
CREATE TABLE `bt` (
  `ID` int(10) NOT NULL,
  `VName` varchar(20) NOT NULL DEFAULT '',
  PRIMARY KEY (`ID`,`VName`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `bt1` (
  `ID` int(10) NOT NULL,
  `VName` varchar(20) NOT NULL DEFAULT '',
  KEY `ID` (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

分别插入10000000条数据 数据格式如下
ID  vname
0   M0
1   M1
然后分别对索引列及非索引列采用两种方式查询。
索引列不存在什么差别,效率差不多。
单是对于非索引列差别相差太大。
查询语句如下
select * from bt left join  ( select bt1.ID from bt1  where bt1.`VName`<'M5' )B1 on bt.ID = b1.`ID`
where bt.ID <1000 --1

select  *
from bt left join  bt1  on bt.ID = bt1.`ID` and bt1.`VName`<'M5'
where bt.ID <1000 --2

语句1花费 1000 rows fetched (24.860 sec)
语句2花费 1000 rows fetched (156 ms)
效率相差不是几倍而是几百倍。

1 楼 xiangzi21 2011-01-18  
写的不错!
不过最后一个例子
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

如果数据量小倒是可以,如果数据量大了mysql对关联字查询的效率不高吧?

相关推荐

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

    在使用LEFT JOIN和RIGHT JOIN时,条件筛选可以使用ON和WHERE子句。它们之间的差异是很多人容易混淆的地方。ON子句是在连接操作中对连接条件进行指定,而WHERE子句通常用于对结果集进行过滤。由于这两者在查询的逻辑...

    Mysql之innerjoin,leftjoin,rightjoin详解.pdf

    Mysql 之 inner join、left join、right join 详解 Mysql 中的连接查询是指从多个表中检索数据,并将它们组合成一个结果集。inner join、left join 和 right join 是 Mysql 中三种最常用的连接查询方式。 inner ...

    MySQL left join操作中on和where放置条件的区别介绍

    在多表查询时,如果连接条件影响到连接的结果,必须将它们放在`ON`后面,以确保`LEFT JOIN`或`RIGHT JOIN`的正确行为。对于不影响连接的条件,放在`ON`或`WHERE`后面都可以,但这不会改变连接类型的效果。 总结一下...

    深入理解mysql之left join 使用详解

    ON 子句与 WHERE 子句的不同 一种更好地理解带有 WHERE … IS NULL 子句的复杂匹配条件的简单方法 Matching-Conditions 与 Where-conditions 的不同 关于 “A LEFT JOIN B ON 条件表达式” 的一点提醒 ON 条件(...

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

    与LEFT JOIN相反,RIGHT JOIN会返回右表的所有记录,即使在左表中没有匹配的记录。在上述文章和用户表的例子中,如果我们想要列出所有用户,以及他们可能拥有的文章,即使某些用户没有发表过文章,可以使用RIGHT ...

    mysql Join使用以及优化

    MySQL数据库中Join操作的使用及优化是一项重要的技能,它涉及到数据库中表与表之间的关联查询。在执行Join操作时,数据库管理系统需要按照某种算法将多个表中的数据记录联合起来,并返回查询结果。Join操作的主要...

    SQL语句优化之JOIN和LEFT JOIN 和 RIGHT JOIN语句的优化

    WHERE和HAVING子句通常与JOIN条件一起优化,但如果WHERE条件排除了LEFT JOIN生成的NULL行,可以转换为等值JOIN,从而提高效率。 RIGHT JOIN 与LEFT JOIN类似,只是角色互换,返回右表的所有行。转换规则与LEFT JOIN...

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

    在MySQL中,LEFT JOIN操作用于将一个表(称为左表)的所有记录与另一个表(称为右表)中匹配的记录组合在一起。如果右表中没有匹配的记录,结果集将包含左表的所有记录,但右表对应列的值将为NULL。当我们设置LEFT ...

    sql中的left join及on、where条件关键字的区别详解

    LEFT JOIN 关键字会从左表 (table_name1) 那里返回所有的行,即使在右表 (table_name2) 中没有匹配的行。 LEFT JOIN 关键字语法 SELECT column_name(s) FROM table_name1 LEFT JOIN table_name2 ON table_name1....

    mysql not in、left join、IS NULL、NOT EXISTS 效率问题记录

    MySQL中的`NOT IN`, `LEFT JOIN`, `IS NULL`, 和 `NOT EXISTS` 是四种不同的SQL查询方式,它们在特定情况下可以实现相似的功能,但实际执行效率可能会有很大差异。本文主要探讨这四种方法在处理大数据量时的性能表现...

    mysql多个left join连接查询用法分析

    MySQL中的LEFT JOIN是一种关联多个表的方法,用于返回左表的所有记录以及右表匹配的记录。在某些场景下,我们可能需要连接多个表来获取全面的数据信息。本篇文章将深入探讨MySQL多个LEFT JOIN连接查询的用法,通过...

    MySQL查询条件中放置on和where的区别分析

    如果在`LEFT JOIN`中同时使用`ON`和`WHERE`,需要注意的是,`WHERE`条件可能会覆盖`ON`条件的效果。在`LEFT JOIN`中,`WHERE`通常用于限制最终结果集的行,而不是影响连接本身。如果`WHERE`子句中包含`JOIN`条件,...

    mysql join所有方法总结

    从内容中可以看出,RIGHT JOIN的使用方法与LEFT JOIN类似,只不过是从右表获取所有数据:SELECT a.*, b.* FROM employee_table a RIGHT JOIN issue b ON a.id = b.id。 FULL JOIN:虽然上述内容中提到MySQL不支持...

    Join on 连接

    在本篇内容中,我们将深入探讨`JOIN`的不同类型,包括`INNER JOIN`、`LEFT JOIN`、`RIGHT JOIN`以及`FULL OUTER JOIN`,并理解它们在实际应用中的差异和作用。 1. **INNER JOIN**(内连接): 内连接只返回两个表...

    MySQL的LEFT JOIN表连接的进阶学习教程

    MySQL的LEFT JOIN是一种关联查询操作,它用于合并两个或多个表的数据,并且返回所有左表(也就是在JOIN语句中位于LEFT关键字之后的表)的记录,即使在右表中没有匹配的记录。这个概念是数据库关系查询中的关键部分,...

Global site tag (gtag.js) - Google Analytics