表连接顺序是否会影响查询结果?

时间:2016-02-29 16:16:35

标签: mysql sql oracle join

有三个表,t1,t2,t3。每个表都有一个字段f。这些sqls对是否相同?

1.select t1.f,t2.f,t3.f from t1 left join t2 on t1.f =t2.f left join t3 on t1.f = t3.f

select t1.f,t2.f,t3.f from t1 left join t3 on t1.f =t3.f left join t2 on t1.f = t2.f

2.select t1.f,t2.f,t3.f from t1 left join t2 on t1.f =t2.f inner join t3 on t1.f = t3.f

select t1.f,t2.f,t3.f from t1 inner join t3 on t1.f =t3.f left join t2 on t1.f = t2.f

3.select t1.f,t2.f,t3.f from t1 left join t2 on t1.f =t2.f right join t3 on t1.f = t3.f

select t1.f,t2.f,t3.f from t1 right join t3 on t1.f =t3.f left join t2 on t1.f = t2.f

4.select t1.f,t2.f,t3.f from t1 left join t2 on t1.f =t2.f full join t3 on t1.f = t3.f

select t1.f,t2.f,t3.f from t1 full join t3 on t1.f =t3.f left join t2 on t1.f = t2.f

5.select t1.f,t2.f,t3.f from t1 left join t2 on t1.f =t2.f left join t3 on t2.f = t3.f

select t1.f,t2.f,t3.f from t1 left join (t2 left join t3 on t2.f = t3.f) on t1.f =t2.f

...保持三个表的任意两个表具有相同的连接和相同的连接字段。查询结果是否相同?如何轻松理解?

我想知道如何证明这一点。当我使用oracle(+)连接表时,我发现(+)不显示表连接顺序。如果结果不同,那么oracle的默认顺序是什么?

我知道t1左连接t2不同于t2左连接t1,因为它转换为(+)是不同的sql。在sql上面,你将其转换为(+)是相同的。

例如最后一对sqls可以从t1,t2,t3转换为选择t1.f,t2.f,t3.f,其中t1(+)= t2和t2(+)= t3,如下所示子句没有顺序。在sql join的wiki中,显式连接和隐式连接是相等的。因此,如果成对的sqls的结果不同,那将是矛盾的。

3 个答案:

答案 0 :(得分:1)

这是我最好的知识:

左连接B. ~A∪(A∩B) ~A

右连接B. 〜(A∩B)∪B ~B

完整加入B. ~A∪B

内部联接B. ~A∩B

#1
t1 ∪ (t1 ∩ t3)                         t1 ∪ (t1 ∩ t2)
~ t1                                   ~ t1 

#2
t1 ∩ t3                                (t1 ∩ t3) ∪ (t1 ∩ t3 ∩ t2) 
~ t1 ∩ t3                              ~ t1 ∩ t3 

#3
(t1 ∩ t3 ) ∪ t3                        t3 ∪ (t1 ∩ t3 ∩ t2)
~ t3                                   ~ t3

#4
t1 ∪ t3                                (t1 ∪ t3) ∪ (t1 ∪ (t1 ∩ t2))
~ t1 ∪ t3                              ~ t1 ∪ t3

#5
(t1 ∪ (t1 ∩ t2)) ∪ (t1 ∩ t2 ∩ t3)      t1 ∪ (t1 ∩ (t2 ∪ (t2 ∩ t3)))
~ t1 ∪ (t1 ∩ t2 ∩ t3)                  ~ t1 ∪ (t1 ∩ t2)
~ t1                                   ~ t1

我试图缩短它,即使是第一个表达式也可以消除混淆。对于#5,我让它更长一点,以便更清楚。如果你想看到完整的扩展表达,请告诉我。

答案 1 :(得分:0)

在左边加入

的结果
from  t1  left join t2 on t1.f1 = t2.f2 

可能与

不同
from  t2  left join t1 on t1.f1 = t2.f2 

如果在第一种情况下在t1中的行不在第二种情况下选择t2中的行,则尝试认为具有空值的列,同一列在这些列中生成具有空值的行。

对于内连接自然没有区别..

答案 2 :(得分:0)

否则INNER加入

不仅结果与DBMS引擎优化查询的结果相同,并且大多数时候查询计划(因此性能)不一样。 没有默认订单。在一些内部优化之后,DBMS很可能会加入表。例如,它可以尝试首先迭代较小的(少行)表。

对于OUTER JOINS ,

查看此案例:您有表A,B和C,并且您查询A和 LEFT JOIN B和C.

create table A 
(
   idA int
  ,idB int
  ,idC int
)

create table B 
(
   idA int
  ,idB int
  ,idC int
)

create table C 
(
   idA int
  ,idB int
  ,idC int
)

insert into A values
(1,1,null),(2,2,null)

insert into B values
(1,1,null),(2,2,null)

现在A中有很多行,对于A中的每一行,B中有一行但C为空。你生病了A x B中的所有行 现在尝试在B之前离开加入C ...

select *
from A
left join B on B.idB = A.idB
left join C on C.idC = B.idC


select *
from A
left join C on C.idC = A.idC
left join B on B.idB = C.idB

......结果不同!

idA         idB         idC         idA         idB         idC         idA         idB         idC
----------- ----------- ----------- ----------- ----------- ----------- ----------- ----------- -----------
1           1           NULL        1           1           NULL        NULL        NULL        NULL
2           2           NULL        2           2           NULL        NULL        NULL        NULL

(2 row(s) affected)

idA         idB         idC         idA         idB         idC         idA         idB         idC
----------- ----------- ----------- ----------- ----------- ----------- ----------- ----------- -----------
1           1           NULL        NULL        NULL        NULL        NULL        NULL        NULL
2           2           NULL        NULL        NULL        NULL        NULL        NULL        NULL

(2 row(s) affected)

另外,根据经验,如果你混合outter和inners连接首先放入内连接,因为在outter join之后的任何连接都是 defacto outter join,即使你打算写一个内连接

OP也询问(+)...暗示加入我猜。显式和隐式连接之间的区别是连接子句在其中子句之前处理。

修改

正如@Michael Broughton评论的那样,如果没有加入链,那么订单并不重要。