`

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筛选的差异

    本篇文章是对mysql left( right )join使用on与where筛选的差异进行了详细的分析介绍,需要的朋友参考下

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

    on的优先级是高于where的。 首先明确两个概念: LEFT JOIN 关键字会从左表 (table_name1) 那里返回所有的行,即使在右表 (table_name2) 中没有匹配的行。 数据库在通过连接两张或多张表来返回记录时,都会生成...

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

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

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

    主要介绍了mysql中left join设置条件在on与where时的用法区别,结合实例形式分析了mysql中left join设置条件在on与where时的相关用法区别与操作注意事项,需要的朋友可以参考下

    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 效率问题记录

    NOT IN、JOIN、IS NULL、NOT EXISTS效率对比 语句一:select count(*) from A where A.a not in (select a from B) 语句二:select count(*) from A left join B on A.a = B.a where B.a is null 语句三:select ...

    MySQL中join语句的基本使用教程及其字段对性能的影响

    … FROM table1 INNER|LEFT|RIGHT JOIN table2 ON conditiona table1 通常称为左表,table2 称为右表。ON 关键字用于设定匹配条件,用于限定在结果集合中想要哪些行。如果需要指定其他条件,后面可以加上 WHERE 条件...

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

    解决办法呢,就是将条件放到 LEFT JOIN 中。 MySQL 语句执行顺序 首先先说明一个概念,MySQL 语句执行的顺序,并不是按照 SQL 语句的顺序。下面是示例 SQL SELECT DISTINCT &lt; select_list &gt; FROM &lt; left&gt; ...

    MySQL IF、 Bewteen、 AS、 Date_Format、Left join on等关键字实例

    我们在写SQL时候,往往会需要格式化或多表联合查询,现在来一个实例看看这个问题 SELECT t.id, t.topic_...LEFT JOIN student_commit_history sch on t.id = sch.topic_id where sch.student_id =41 AND sch.create_t

    mysql查询优化的若干

    mysql_查询语句优化.MySQL怎样优化LEFT JOIN 在MySQL中,A LEFT JOIN B实现如下: 1、表B被设置为依赖于表A。 2、表A被设置为依赖于所有用在LEFT JOIN条件的表(除B外)。 3、所有LEFT JOIN条件被移到WHERE子句中...

    MySQL中基本的多表连接查询教程

    一、多表连接类型 1. 笛卡尔积(交叉连接) ...一般使用LEFT [OUTER] JOIN或者RIGHT [OUTER] JOIN  2. 内连接INNER JOIN 在MySQL中把I SELECT * FROM table1 CROSS JOIN table2 SELECT * FROM table1 JOIN table2 SELE

    MySql 5.1 参考手册.chm

    7.2.9. MySQL如何优化LEFT JOIN和RIGHT JOIN 7.2.10. MySQL如何优化嵌套Join 7.2.11. MySQL如何简化外部联合 7.2.12. MySQL如何优化ORDER BY 7.2.13. MySQL如何优化GROUP BY 7.2.14. MySQL如何优化LIMIT 7.2.15. ...

    MySQL查询把多列返回结果集拼装成一个字段

    mysql中有种可以通过join相关操作进行表与表之间的方式查询不同结果集,但是在一对多的情况下,关键查询的结果是多条的.例如:班级和学习的关系,我想很直观的看到班级和学生的情况,列表显示出班级的信息和班级的男生...

    MySQL 5.1参考手册

    7.2.9. MySQL如何优化LEFT JOIN和RIGHT JOIN 7.2.10. MySQL如何优化嵌套Join 7.2.11. MySQL如何简化外部联合 7.2.12. MySQL如何优化ORDER BY 7.2.13. MySQL如何优化GROUP BY 7.2.14. MySQL如何优化LIMIT ...

    mysql查询必练50题

    LEFT JOIN SC b ON b.cid=01 AND a.sid=b.sid LEFT JOIN SC c ON c.cid=02 AND a.sid=c.sid WHERE b.score&gt;c.score; -- 2、查询平均成绩大于60分的同学的学号和平均成绩; SELECT sid 学号, AVG(score) 平均成绩...

    MySQL数据库:USING子句.pptx

    表名1 LEFT| RIGHT JOIN 表名2 USING (列名) [WHERE 条件表达式] ; 【例】 查找Members表中所有订购过图书的会员的姓名。 SELECT Distinct 姓名 FROM Members JOIN Sell USING (用户号); 与下列语句等价: SELECT ...

    MySQL 5.1中文手冊

    7.2.9. MySQL如何优化LEFT JOIN和RIGHT JOIN 7.2.10. MySQL如何优化嵌套Join 7.2.11. MySQL如何简化外部联合 7.2.12. MySQL如何优化ORDER BY 7.2.13. MySQL如何优化GROUP BY 7.2.14. MySQL如何优化LIMIT 7.2.15. ...

    MYSQL

    10.5.2 SELECT 查询的速度 10.5.3 MySQL 怎样优化WHERE子句 10.5.4 MySQL 怎样优化LEFT JOIN 10.5.5 MySQL 怎样优化LIMIT 10.5.6 INSERT查询的速度 10.5.7 UPDATE查询的速度 10.5.8 ...

Global site tag (gtag.js) - Google Analytics