2012-09-13 46 views
18

Sql语句。SQL左连接中的“on ..和”与“on .. where”之间的区别?

1.select a.* from A a left join B b on a.id =b.id and a.id=2; 

2.select a.* from A a left join B b on a.id =b.id where a.id=2; 

这两个sql语句有什么区别?

+1

http://stackoverflow.com/questions/10297231/where-clause-vs-on-when-using-join – Habib

+4

不是重复的,在这里'LEFT JOIN'显着改变了这个问题。 – hvd

+1

@hvd - 问题可能不完全相同,但由于大部分的答案是沿着线“没关系的'INNER JOIN',但这里是什么将是'OUTER JOIN's不同... “ –

回答

23
create table A(id int); 
create table B(id int); 

INSERT INTO A VALUES(1); 
INSERT INTO A VALUES(2); 
INSERT INTO A VALUES(3); 

INSERT INTO B VALUES(1); 
INSERT INTO B VALUES(2); 
INSERT INTO B VALUES(3); 

SELECT * FROM A; 
SELECT * FROM B; 

id 
----------- 
1 
2 
3 

id 
----------- 
1 
2 
3 

滤波器。

select a.*,b.* 
from A a left join B b 
on  a.id =b.id and a.id=2; 

id   id 
----------- ----------- 
1   NULL 
2   2 
3   NULL 

在JOIN发生后将会过滤WHERE。

select a.*,b.* 
from A a left join B b 
on  a.id =b.id 
where a.id=2; 

id   id 
----------- ----------- 
2   2 
+0

感谢您详细讲解 –

+0

@ jack.li高兴帮助你:) –

+0

出于某种原因,如预期在这个sqlfiddle它没有工作:http://sqlfiddle.com/#!2/9684d/4 但是,当我在MySQL尝试它,你说这工作完全。 –

8

从a向左连接b b,从a.id = b.id和a.id = 2中选择a *。

这只在连接条件中使用a.id,所以记录a.id <> 2不会被过滤掉。你可能会得到这样的结果:

 
+------+------+ 
| a.id | b.id | 
+------+------+ 
| 1 | NULL | 
| 2 | 2 | 
| 3 | NULL | 
+------+------+ 

您不选择任何b的列,但如果这样做,它会更容易理解。

选择a。* from a a a left join b b on a.id = b.id where a.id = 2;

现在记录a.id <> 2确实被滤除了。对JOIN,以防止在连接过程被添加的行

 
+------+------+ 
| a.id | b.id | 
+------+------+ 
| 2 | 2 | 
+------+------+ 
0

由于@hvd说,“去哪儿”条款滤波由加盟返回的行,因此,“这里的”版本将不会返回外连排(有a.id = NULL)。

但是还有另外一个显着的区别:即使外部连接的行没有被过滤出来,也可以通过将条件放入“on”子句来提高性能,因为结果集较小。

当一系列其他左连接表遵循具有“和”条件的连接表时,这一点尤为明显 - 您可以防止连接发生不适合下表的不适合的行,并有可能阻止数百万行到达过滤(“where”)阶段。

0

我试了一些时间,我知道是什么原因,它只关系到优先级。

select * from A a left join B b on a.id=b.id and b.id=2 

这意味着左连接(其中b.id = 2),这是条件 滤波器B第一

Select * from A a left join B b on a.id=b.id where a.id=2 

此装置加入B之后,再由a.id = 2

过滤
0

如果您考虑SQL查询的语法,那么'AND'会扩展连接块(就像括号一样),其中'WHERE'定义查询的WHERE /过滤块的起始位置。

相关问题