如何理解一个左连接B ......左连接C on ..?

时间:2014-04-27 21:20:59

标签: sql left-join

我知道左边的连接是如何为两个表工作的​​,但它如何适用于三个(或更多)表?

SELECT col FROM table1 t1 
     LEFT JOIN table2 t2 ON t1.col = t2.col
     LEFT JOIN table3 t3 ON t1.col = t3.col
     LEFT JOIN table4 t4 ON t1.col = t4.col
     -- ...
     WHERE ...

如何解释这句话?

更新

如果你进行三重连接会得到什么结果?应用左连接的后果?

5 个答案:

答案 0 :(得分:1)

像这样:

SELECT col FROM table1 t1 
    LEFT JOIN table2 t2 ON t1.col = t2.col
    -- first join will return each statement of table1 and table2 where t1.col = t2.col or where t1.col not in t2 (with null value in the right side columns)
    LEFT JOIN table3 t3 ON t1.col = t3.col
    -- second join will do the same but with each statement of the result of the previous join as a temporarily table
    LEFT JOIN table4 t4 ON t1.col = t4.col
    -- ...
    WHERE ...

答案 1 :(得分:1)

当您使用多个LEFT JOIN时,您必须将此解释为表格上的空值的可能性。在您的示例中,对于只返回值的查询,Table1需要有记录。你可以有空的table2,table3和table4,你的查询无论如何都会返回值。以此查询为例:

SELECT *
  FROM Prices P
 RIGHT JOIN Articles A ON P.ArticleID = A.ArticleID
  LEFT JOIN Sales S    ON S.ArticleID = A.ArticleID

在这种情况下,您可以获得整个文章表格,如果您有特定文章的价格或销售额,您也可以获得该信息,但您始终可以获得所有文章。

答案 2 :(得分:1)

让我们重新想象一下原始SQL如何用一种伪代码表示。允许Join( table1_expression , table2_expression , on_condition )表示LEFT JOIN操作,其结果是未命名的临时表。

-- Pseudo-code for: FROM table1 t1
LET t1 = table1

-- Pseudo-code for: LEFT JOIN table2 t2 ON t1.col = t2.col
LET t2 = table2
LET S1 = Join(t1, t2, t1.col = t2.col)

此处S1是对结果(未命名的临时)表的引用,该表是LEFT JOIN的行。既然你已经知道LEFT JOIN对两个表的作用,那么就没有必要进入这里了。但应该说这个S1包含t1t2的所有列。因此,为了便于讨论,我们假设在此伪代码中,t1的所有S1列的格式为S1.t1.*;以及所有t2列,S1.t2.*。例如。 t1.col中的t2.colS1S1.t1.colS1.t2.col

-- Pseudo-code for: LEFT JOIN table3 t3 ON t1.col = t3.col
LET t3 = table3
LET S2 = Join(S1, t3, S1.t1.col = t3.col)

此处S1被视为与任何其他表格一样。 S1.t1.col只是我们将原始SQL的t1.col解释为伪代码。

好的,到目前为止,伪代码(功能上)反映了现实SQL中发生的事情。首先,它以t1(table1)作为查询结果开始。然后由于第一个S1,它转到LEFT JOIN。从那里,查询结果变为S2行,第二行LEFT JOIN

-- Pseudo-code for: LEFT JOIN table4 t4 ON t1.col = t4.col
LET t4 = table4
LET S3 = Join(S2, t4, S2.t1.col = t4.col)

查询的最终结果随后的每个LEFT JOIN而变化。请注意,每个表的每一列都在播放(即table1到table4),当然,系统会处理SELECT(说到哪一个,你的例子需要SELECT t1.col,因为一列名字col在你的所有表格中。此外,WHERE会过滤掉S3中的行,这些行是您的示例SQL的实际结果。


应该指出的是,真正的SQL数据库可能不会像伪代码那样使临时表执行LEFT JOIN。但是,从功能上讲,返回的行将是相同的。

答案 3 :(得分:1)

如果有4个表,可以使用不同的方法配置LEFT JOIN。

查询1

在您提出的问题中(或多或少):

SELECT t1.col, t2.info2, t3.info3, t4.info4
  FROM      table1 t1 
  LEFT JOIN table2 t2 ON t1.col = t2.col
  LEFT JOIN table3 t3 ON t1.col = t3.col
  LEFT JOIN table4 t4 ON t1.col = t4.col
 WHERE ...

请注意,我通过从每个表中选择一个值来确保每个表都是必需的。例如,如果没有从Table4中选择列,那么查询优化器可能会发现并推断出它甚至不需要查看Table4。

查询有点像雪花;表1(左)依次连接表2,表3和表4。 Table1中与WHERE子句中的条件匹配的所有行都将出现在输出中(至少一次)。如果Table2中有任何与ON t1.col = t2.col条件匹配的行,则会选择它们;如果没有这样的行,将使用一行NULL。假设Table2中有2行与Table1中的R1匹配,Table3中有3行与Table1中的R1匹配,Table4中有4行与R1匹配。然后在R1的输出中将有24行(除非WHERE子句消除了其中的一些)。

查询2

SELECT t1.col, t2.info2, t3.info3, t4.info4
  FROM      table1 t1 
  LEFT JOIN table2 t2 ON t1.col = t2.col
  LEFT JOIN table3 t3 ON t2.col = t3.col
  LEFT JOIN table4 t4 ON t3.col = t4.col
 WHERE ...

这是一个完全不同的查询。它是一个长链:Table1连接到Table2;表2加入表3;和表3连接到表4。

显然,如果您愿意,也可以采用其他方式加入表格。

样本数据

考虑这些数据。 Informix的语法是正确的,但如果用于创建临时表的TEMP表示法对DBMS不起作用,请删除关键字TEMP,它应该没问题。

CREATE TEMP TABLE table1 (col CHAR(2) NOT NULL PRIMARY KEY, info1 CHAR(15) NOT NULL);
INSERT INTO table1 VALUES('R1', 'Info T1 R1');
INSERT INTO table1 VALUES('R2', 'Info T1 R2');
INSERT INTO table1 VALUES('R3', 'Info T1 R3');
INSERT INTO table1 VALUES('R4', 'Info T1 R4');
INSERT INTO table1 VALUES('R5', 'Info T1 R5');
INSERT INTO table1 VALUES('R6', 'Info T1 R6');
INSERT INTO table1 VALUES('R7', 'Info T1 R7');
INSERT INTO table1 VALUES('R8', 'Info T1 R8');
CREATE TEMP TABLE table2 (col CHAR(2) NOT NULL, info2 CHAR(15) NOT NULL, sub2 INTEGER, PRIMARY KEY(col, sub2));
INSERT INTO table2 VALUES('R1', 'Info T2 R1 V1', 1); 
INSERT INTO table2 VALUES('R1', 'Info T2 R1 V2', 2); 
INSERT INTO table2 VALUES('R2', 'Info T2 R2 V1', 1); 
INSERT INTO table2 VALUES('R5', 'Info T2 R5 V1', 1); 
INSERT INTO table2 VALUES('R6', 'Info T2 R6 V1', 1); 
INSERT INTO table2 VALUES('R7', 'Info T2 R7 V1', 1); 
CREATE TEMP TABLE table3 (col CHAR(2) NOT NULL, info3 CHAR(15) NOT NULL, sub3 INTEGER, PRIMARY KEY(col, sub3));
INSERT INTO table3 VALUES('R1', 'Info T3 R1 V1', 11);
INSERT INTO table3 VALUES('R1', 'Info T3 R1 V2', 12);
INSERT INTO table3 VALUES('R1', 'Info T3 R1 V3', 13);
INSERT INTO table3 VALUES('R3', 'Info T3 R3 V1', 11);
INSERT INTO table3 VALUES('R5', 'Info T3 R5 V1', 11);
INSERT INTO table3 VALUES('R6', 'Info T3 R6 V1', 11);
CREATE TEMP TABLE table4 (col CHAR(2) NOT NULL, info4 CHAR(15) NOT NULL, sub4 INTEGER, PRIMARY KEY(col, sub4));
INSERT INTO table4 VALUES('R1', 'Info T4 R1 V1', 21);
INSERT INTO table4 VALUES('R1', 'Info T4 R1 V2', 22);
INSERT INTO table4 VALUES('R1', 'Info T4 R1 V3', 23);
INSERT INTO table4 VALUES('R1', 'Info T4 R1 V4', 24);
INSERT INTO table4 VALUES('R4', 'Info T4 R4 V1', 21);
INSERT INTO table4 VALUES('R5', 'Info T4 R5 V1', 21);
INSERT INTO table4 VALUES('R5', 'Info T4 R5 V2', 22);

两个查询的输出不同。完全省略了WHERE子句。

查询1的输出

R1  Info T2 R1 V1   Info T3 R1 V1   Info T4 R1 V1
R1  Info T2 R1 V1   Info T3 R1 V1   Info T4 R1 V2
R1  Info T2 R1 V1   Info T3 R1 V1   Info T4 R1 V3
R1  Info T2 R1 V1   Info T3 R1 V1   Info T4 R1 V4
R1  Info T2 R1 V2   Info T3 R1 V1   Info T4 R1 V1
R1  Info T2 R1 V2   Info T3 R1 V1   Info T4 R1 V2
R1  Info T2 R1 V2   Info T3 R1 V1   Info T4 R1 V3
R1  Info T2 R1 V2   Info T3 R1 V1   Info T4 R1 V4
R1  Info T2 R1 V1   Info T3 R1 V2   Info T4 R1 V1
R1  Info T2 R1 V1   Info T3 R1 V2   Info T4 R1 V2
R1  Info T2 R1 V1   Info T3 R1 V2   Info T4 R1 V3
R1  Info T2 R1 V1   Info T3 R1 V2   Info T4 R1 V4
R1  Info T2 R1 V2   Info T3 R1 V2   Info T4 R1 V1
R1  Info T2 R1 V2   Info T3 R1 V2   Info T4 R1 V2
R1  Info T2 R1 V2   Info T3 R1 V2   Info T4 R1 V3
R1  Info T2 R1 V2   Info T3 R1 V2   Info T4 R1 V4
R1  Info T2 R1 V1   Info T3 R1 V3   Info T4 R1 V1
R1  Info T2 R1 V1   Info T3 R1 V3   Info T4 R1 V2
R1  Info T2 R1 V1   Info T3 R1 V3   Info T4 R1 V3
R1  Info T2 R1 V1   Info T3 R1 V3   Info T4 R1 V4
R1  Info T2 R1 V2   Info T3 R1 V3   Info T4 R1 V1
R1  Info T2 R1 V2   Info T3 R1 V3   Info T4 R1 V2
R1  Info T2 R1 V2   Info T3 R1 V3   Info T4 R1 V3
R1  Info T2 R1 V2   Info T3 R1 V3   Info T4 R1 V4
R2  Info T2 R2 V1
R3                  Info T3 R3 V1
R4                                  Info T4 R4 V1
R5  Info T2 R5 V1   Info T3 R5 V1   Info T4 R5 V1
R5  Info T2 R5 V1   Info T3 R5 V1   Info T4 R5 V2
R6  Info T2 R6 V1   Info T3 R6 V1
R7  Info T2 R7 V1
R8

查询2的输出

R1  Info T2 R1 V1   Info T3 R1 V1   Info T4 R1 V1
R1  Info T2 R1 V1   Info T3 R1 V1   Info T4 R1 V2
R1  Info T2 R1 V1   Info T3 R1 V1   Info T4 R1 V3
R1  Info T2 R1 V1   Info T3 R1 V1   Info T4 R1 V4
R1  Info T2 R1 V1   Info T3 R1 V2   Info T4 R1 V1
R1  Info T2 R1 V1   Info T3 R1 V2   Info T4 R1 V2
R1  Info T2 R1 V1   Info T3 R1 V2   Info T4 R1 V3
R1  Info T2 R1 V1   Info T3 R1 V2   Info T4 R1 V4
R1  Info T2 R1 V1   Info T3 R1 V3   Info T4 R1 V1
R1  Info T2 R1 V1   Info T3 R1 V3   Info T4 R1 V2
R1  Info T2 R1 V1   Info T3 R1 V3   Info T4 R1 V3
R1  Info T2 R1 V1   Info T3 R1 V3   Info T4 R1 V4
R1  Info T2 R1 V2   Info T3 R1 V1   Info T4 R1 V1
R1  Info T2 R1 V2   Info T3 R1 V1   Info T4 R1 V2
R1  Info T2 R1 V2   Info T3 R1 V1   Info T4 R1 V3
R1  Info T2 R1 V2   Info T3 R1 V1   Info T4 R1 V4
R1  Info T2 R1 V2   Info T3 R1 V2   Info T4 R1 V1
R1  Info T2 R1 V2   Info T3 R1 V2   Info T4 R1 V2
R1  Info T2 R1 V2   Info T3 R1 V2   Info T4 R1 V3
R1  Info T2 R1 V2   Info T3 R1 V2   Info T4 R1 V4
R1  Info T2 R1 V2   Info T3 R1 V3   Info T4 R1 V1
R1  Info T2 R1 V2   Info T3 R1 V3   Info T4 R1 V2
R1  Info T2 R1 V2   Info T3 R1 V3   Info T4 R1 V3
R1  Info T2 R1 V2   Info T3 R1 V3   Info T4 R1 V4
R2  Info T2 R2 V1
R3
R4
R5  Info T2 R5 V1   Info T3 R5 V1   Info T4 R5 V1
R5  Info T2 R5 V1   Info T3 R5 V1   Info T4 R5 V2
R6  Info T2 R6 V1   Info T3 R6 V1
R7  Info T2 R7 V1
R8

答案 4 :(得分:0)

您可以根据需要将多个表连接在一起。有关三个表的示例,请参见下文。对于您必须加入第三个表的列以及之后的每个表都没有限制。

SELECT a.*, b.*, c.* 
FROM [first_table] as a

LEFT JOIN [second_table] as b
ON a.some_column = b.some_other_column

LEFT JOIN [third_table] as c
ON a.some_second_column = c.yet_another_column