无视性能,我会从下面的查询A和B得到相同的结果吗? C和D怎么样?
-- A
select *
from a left join b
on <blahblah>
left join c
on <blahblan>
-- B
select *
from a left join c
on <blahblah>
left join b
on <blahblan>
-- C
select *
from a join b
on <blahblah>
join c
on <blahblan>
-- D
select *
from a join c
on <blahblah>
join b
on <blahblan>
对于INNER
加入,不,顺序无关紧要。只要您将选择从SELECT *
更改为SELECT a.*, b.*, c.*
,查询将返回相同的结果。
对于(LEFT
,RIGHT
或FULL
)OUTER
加入,是的,顺序很重要 - 而且(更新)事情要复杂得多。
首先,外连接不是可交换的,所以a LEFT JOIN b
与b LEFT JOIN a
不同
外连接也不是关联的,因此在您的示例中涉及(交换性和关联性)属性:
a LEFT JOIN b
ON b.ab_id = a.ab_id
LEFT JOIN c
ON c.ac_id = a.ac_id
相当于:
a LEFT JOIN c
ON c.ac_id = a.ac_id
LEFT JOIN b
ON b.ab_id = a.ab_id
但:
a LEFT JOIN b
ON b.ab_id = a.ab_id
LEFT JOIN c
ON c.ac_id = a.ac_id
AND c.bc_id = b.bc_id
不等于:
a LEFT JOIN c
ON c.ac_id = a.ac_id
LEFT JOIN b
ON b.ab_id = a.ab_id
AND b.bc_id = c.bc_id
另一个(希望更简单)相关性的例子。把它想象为(a LEFT JOIN b) LEFT JOIN c
:
a LEFT JOIN b
ON b.ab_id = a.ab_id -- AB condition
LEFT JOIN c
ON c.bc_id = b.bc_id -- BC condition
这相当于a LEFT JOIN (b LEFT JOIN c)
:
a LEFT JOIN
b LEFT JOIN c
ON c.bc_id = b.bc_id -- BC condition
ON b.ab_id = a.ab_id -- AB condition
只是因为我们有“好”的ON
条件。 ON b.ab_id = a.ab_id
和c.bc_id = b.bc_id
都是平等检查,不涉及NULL
比较。
您甚至可以与其他运营商或更复杂的运营商有条件:ON a.x <= b.x
或ON a.x = 7
或ON a.x LIKE b.x
或ON (a.x, a.y) = (b.x, b.y)
,这两个查询仍然是等效的。
但是,如果其中任何一个涉及IS NULL
或与COALESCE()
等空值相关的函数,例如,如果条件是b.ab_id IS NULL
,那么这两个查询将不相等。
对于常规联接,它没有。 TableA join TableB
将生成与TableB join TableA
相同的执行计划(因此您的C和D示例将是相同的)
它适用于左右连接。 TableA left Join TableB
与TableB left Join TableA
不同,但它与TableB right Join TableA
相同
如果你在加入B之前尝试在B的字段上加入C,即:
SELECT A.x, A.y, A.z FROM A
INNER JOIN C
on B.x = C.x
INNER JOIN b
on A.x = B.x
您的查询将失败,因此在这种情况下,订单很重要。
Oracle优化器为内连接选择表的连接顺序。优化器仅在简单的FROM子句中选择表的连接顺序。您可以在他们的网站上查看oracle文档。对于左,右外连接,最多投票的答案是正确的。优化器选择最佳连接顺序以及每个表的最佳索引。连接顺序可以影响哪个索引是最佳选择。如果表是内部表,优化器可以选择索引作为表的访问路径,但如果它是外部表,则不能选择索引(并且没有其他限定条件)。
优化器仅在简单的FROM子句中选择表的连接顺序。使用JOIN关键字的大多数联接被展平为简单联接,因此优化程序选择其联接顺序。
优化器不选择外连接的连接顺序;它使用语句中指定的顺序。
选择连接顺序时,优化程序会考虑:每个表的大小每个表上可用的索引表上的索引是否在特定连接顺序中有用每个表中每个表要扫描的行数和页数加入订单