联接顺序在SQL中重要吗?


189

无论性能如何,下面的查询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>  

11
什么<blahblah>啊 您是将A加入B和A加入C,还是将A加入B和B加入C?
beny23

2
嗨,贝尼,我的问题中的代码是抽象的。我并不担心将A到B或A到C联接起来,我只是想知道这样的语法将提供相同的结果。
只是一个学习者

Answers:


225

对于INNER联接,不,顺序无关紧要。该查询将返回相同的结果,只要你改变你的选择SELECT *SELECT a.*, b.*, c.*


对于(LEFTRIGHTFULLOUTER连接,是的,顺序是有意义的-和(更新)事情要复杂得多。

首先,外部联接不是可交换的,因此a LEFT JOIN bb 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_idc.bc_id = b.bc_id是平等的检查,不涉及NULL比较。

您甚至可以与其他运算符或更复杂的运算符(例如:ON a.x <= b.xor ON a.x = 7ON a.x LIKE b.xor)一起使用ON (a.x, a.y) = (b.x, b.y),两个查询仍然相等。

但是,如果其中涉及任何IS NULL一个或与null有关的函数COALESCE()(例如,如果条件为)b.ab_id IS NULL,则这两个查询将不相等。


3
正确地说,只要一个表中所有列均为NULL的行都不能满足谓词,那么外部联接就是关联的,而只要谓词不涉及IS NULL或“与null相关的函数”。可以轻松地想象一个满足前一种描述但不满足后者的谓词,例如a.somecol > 0 OR b.someothercol > 0;在这种情况下,关联性可能会失败。
Mark Amery

但是,是的,我认为说OUTER JOIN是关联的在技术上是正确的,只要该谓词不满足我在此处描述的任何一个条件:stackoverflow.com/questions/20022196/…(其中第一个也打破了关联性)对于INNER JOINs,但是这种廉价且明显的破坏方法,也许不值得一提。)还值得指出的是,最常见的一种JOIN-在外键上进行JOIN-不满足这两个条件中的任何一个因此很友善和友善。
Mark Amery

1
@MarkAmery谢谢你,我当时很难安排句子的结构(而且我已经赞成你的回答了;)
ypercubeᵀᴹ2013年

ypercube我有一个INNER JOIN和以下LEFT JOIN。它的工作原理一样,先查询将Filter底座上的记录INNER JOIN,然后将适用LEFT JOINFiltered记录?
穆罕默德·巴巴尔

实际上,按照SQL标准并根据关联性的数学定义,所有联接类型都是关联性的,但是它们看起来并不具有关联性,因为重新排列括号需要将ON子句(即“ 联接规范”)移动到新位置。不过,这只是语法。如果使用关系代数表示法(将连接规范放置在连接运算符下方),则关联性将变得更加明显。您的论点仅显示外部联接不是可交换的,这是正确的
Lukas Eder 2015年

4

对于常规加入,则不是。TableA join TableB将产生与相同的执行计划TableB join TableA(因此您的C和D示例将是相同的)

为左右联接它做。TableA left Join TableB与有所不同TableB left Join TableA,但与TableB right Join TableA


4
这仅解决可交换性,但问题中的示例表明,问询者对结社性感兴趣。ypercube的答案都解决了。
Mark Amery 2014年

2

如果在加入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

您的查询将失败,因此在这种情况下顺序很重要。


是的,这是正确的,应该修改正确的答案。
尼·彭加斯

-2

Oracle优化器为内部联接选择表的联接顺序。Optimizer仅在简单的FROM子句中选择表的连接顺序。您可以在其网站上查看oracle文档。对于左,右外部联接,投票率最高的答案是正确的。优化器为每个表选择最佳的连接顺序以及最佳的索引。连接顺序会影响哪个索引是最佳选择。如果它是内部表,则优化器可以选择索引作为表的访问路径;如果它是外部表,则优化器可以选择索引(并且没有其他条件)。

优化器仅在简单的FROM子句中选择表的连接顺序。大多数使用JOIN关键字的联接被展平为简单的联接,因此优化器选择它们的联接顺序。

优化器不为外部联接选择联接顺序;而是为外部联接选择联接顺序。它使用语句中指定的顺序。

选择连接顺序时,优化器将考虑以下因素:每个表的大小每个表上可用的索引在特定的连接顺序中表上的索引是否有用在每个表中每个表要扫描的行数和页数加盟订单

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.