查询加入等价?

时间:2011-11-21 12:39:54

标签: sql database oracle

这两个查询是否等效(假设表格中有不同的/任何类型的数据)?是否有任何情况会导致不同的结果?

查询1:

select * from tablea a
left join tableb b on a.keyacol = b.keybcol
inner join tablec c on c.keyccol = b.keybcol;

查询2:

select * from tablea a
left join (
select b.*, c.* from tableb b
inner join tablec c on c.keyccol = b.keybcol
) sub on a.keyacol = sub.keybcol;

3 个答案:

答案 0 :(得分:7)

不,他们不等同。例如:

CREATE TABLE a
( keya int ) ;

CREATE TABLE b
( keyb int ) ;

CREATE TABLE c
( keyc int ) ;

INSERT INTO a
  VALUES
  (1) ;

INSERT INTO b
  VALUES
  (1),(2) ;

INSERT INTO c
  VALUES
  (2) ;

结果:

SELECT * 
FROM  a
  LEFT JOIN b 
    ON a.keya = b.keyb
  INNER JOIN c 
    ON c.keyc = b.keyb ;

Result
----------------------
| keya | keyb | keyc |
----------------------


SELECT * 
FROM a
  LEFT JOIN 
    ( SELECT b.*, c.* 
      FROM  b
        INNER JOIN c 
          ON c.keyc = b.keyb
    ) sub 
    ON a.keya = sub.keyb ;

Result
----------------------
| keya | keyb | keyc |
----------------------
|   1  | NULL | NULL |
----------------------

至于为什么会发生这种情况,a LEFT JOIN b INNER JOIN c被解析为(a LEFT JOIN b) INNER JOIN c,相当于(a INNER JOIN b) INNER JOIN c,因为INNER加入条件会取消LEFT加入

您也可以使用此子表单编写第二个查询 - 没有子查询 - 由于a LEFT JOIN (b INNER JOIN c)子句的位置不同而被解析为ON

SELECT * 
FROM a
  LEFT JOIN 
        b
      INNER JOIN c 
        ON c.keyc = b.keyb
    ON a.keya = b.keyb ;

Result
----------------------
| keya | keyb | keyc |
----------------------
|   1  | NULL | NULL |
----------------------

答案 1 :(得分:3)

  

INNER JOIN 关键字在至少有一个匹配项时返回行   两个表/选择。如果tableb中有行没有   <{1}}中的匹配项,不会列出这些行。

     

LEFT JOIN 关键字返回左表中的所有行   (tablec),即使右表中没有匹配项(tablea或   tableb选择)。

由于左连接返回所有行,如果第一个查询的内连接中没有任何对应匹配,则两个查询可能不同。这些行不会在第一个查询中被选中,但会出现在第二个查询中,因为它使用了左连接。

另一个不同的是柱子。但是,由于sub您将从所有表格/选择中选择所有列并且:

  • 查询1返回tablea,tableb和tablec
  • 中的所有列
  • 查询2返回tablea和selection子句中的所有列(返回tableb和tablec中的所有列)=返回tablea,tableb和tablec中的所有列

这不是问题。

所以,它们是等价的。

答案 2 :(得分:3)

他们不等同。

基本上,这里有四种情况,对于A:

上的记录
  1. 存在B和C的相应记录;
  2. B上存在相应的记录但不存在C;
  3. 相应的记录存在于C而不是B;
  4. B或C上不存在相应的记录。
  5. 两个查询都将返回方案1的相同值。

    但是,它们将为其他方案返回不同的值 - 第一个查询中B值与C值的内部连接意味着您将尝试在其他方案中将null连接到值C