[英]MySQL placement of conditions in on-clauses of multiple outer joins
As a follow up to In SQL / MySQL, what is the difference between "ON" and "WHERE" in a join statement? 作为后续工作, 在SQL / MySQL中,join语句中的“ ON”和“ WHERE”之间有什么区别? and SQL join: where clause vs. on clause - it does matter if a condition is placed in the on-clause vs. the where-clause in an outer join.
和SQL加盟:where子句主场迎战一对条款 - 这非常重要,如果条件放在上子句与在WHERE子句中的外部联接。
However, does it matter which on-clause the condition is placed in when there are multiple outer joins? 但是,当有多个外部联接时,条件放在哪个子句上是否重要?
For example, could these produce different results? 例如,这些会产生不同的结果吗?
select * from t1 left join t2 on t1.fid=t2.id and t2.col=val
left join t3 on t2.fid=t3.id;
vs: VS:
select * from t1 left join t2 on t1.fid=t2.id
left join t3 on t2.fid=t3.id and t2.col=val;
Absolutely they are different. 绝对是不同的。
The fisrt query will only have t2
rows that satisfy t2.col=val
t2.col=val
查询将仅包含满足t2
行t2.col=val
The second query will include all t2
rows and only list t3
when t2.col=val
第二个查询将包括所有
t2
行,并且仅当t2.col=val
时列出t3
The queries are not equivalent. 查询不等效。 It is easy to construct a counter example:
构造一个反例很容易:
create table t1 (id int not null, val int not null);
create table t2 (id int not null, val int not null);
create table t3 (id int not null, val int not null);
insert into t1 (id, val) values (1,1);
insert into t2 (id, val) values (1,1);
insert into t3 (id, val) values (1,1);
select * from t1
left join t2
on t1.id = t2.id
and t2.val = 2
left join t3
on t2.id = t3.id;
+----+-----+------+------+------+------+
| id | val | id | val | id | val |
+----+-----+------+------+------+------+
| 1 | 1 | NULL | NULL | NULL | NULL |
+----+-----+------+------+------+------+
select * from t1
left join t2
on t1.id = t2.id
left join t3
on t2.id = t3.id
and t2.val = 2;
+----+-----+------+------+------+------+
| id | val | id | val | id | val |
+----+-----+------+------+------+------+
| 1 | 1 | 1 | 1 | NULL | NULL |
+----+-----+------+------+------+------+
This is one of the queries: 这是查询之一:
select *
from t1 left join
t2
on t1.fid = t2.id left join
t3
on t2.fid = t3.id and t2.col = val;
Yes, the results are different. 是的,结果不同。 If you were using
inner join
they would be the same, but the left join
changes things -- because the join
clause does not do any filtering of rows. 如果您使用
inner join
它们将是相同的,但是left join
改变事情-因为join
子句不会对行进行任何过滤。
I think the simplest explanation is that the join between t1
and t2
will include all rows from t1
as well as all matching rows from t2
-- even those where t2.col <> val
. 我认为最简单的解释是
t1
和t2
之间的t2.col <> val
将包括t1
所有行以及t2
所有匹配行-甚至包括那些t2.col <> val
。 These remain in the result set, because the next left join
does not filter them out. 这些保留在结果集中,因为下一个
left join
不会将它们过滤掉。
In fact, the condition t2.col = val
in the second on
clause does not affect which rows are in the result set. 实际上,第二个
on
子句中的条件t2.col = val
不会影响结果集中的行。 If there is a match, then the row from t3
stays based on the first condition. 如果存在匹配项,则
t3
的行将基于第一个条件停留。 If there is no match, then the row from t3
is still in the result set -- but the t3
columns will be NULL
. 如果没有匹配项,则
t3
的行仍在结果集中-但t3
列将为NULL
。
In this version: 在此版本中:
select *
from t1 left join
t2
on t1.fid = t2.id and t2.col = val left join
t3
on t2.fid = t3.id;
The first join gets all rows from t1
and only matching rows from t2
where t2.col = val
. 第一个
t2.col = val
从t1
获得所有行,并且仅从t2
获得匹配行,其中t2.col = val
。 The third join can then add more rows. 然后,第三个联接可以添加更多行。
Note: there are definitely situations where the two queries would return the same results. 注意:在某些情况下,两个查询将返回相同的结果。 But, the following data would generate different results (assume val = 0):
但是,以下数据将产生不同的结果(假设val = 0):
t1 T1
fid
1
t2 T2
fid col
1 0
1 1
t3 T3
id
1
The query with the condition in the second on
clause will return: 在第二个
on
子句中具有条件的查询将返回:
1 1 0 1
1 1 1 NULL
The query with the condition in the first on
clause will return: 在第一个
on
子句中具有条件的查询将返回:
1 1 0 1
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.