有三个表,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的结果不同,那将是矛盾的。
答案 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)
不仅结果与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评论的那样,如果没有加入链,那么订单并不重要。