在SQL中,Join和多个JOINS结束后的ON条件有什么不同

时间:2012-08-30 11:00:43

标签: sql sql-server

我一直很难在Google上搜索答案,但.... 有人可以向我解释将JOIN的ON条件与JOIN本身相对而将ON置于所有其他JOIN的末尾之间的区别。

这是一个示例http://sqlfiddle.com/#!3/e0a0f/3

CREATE TABLE TableA (Email VARCHAR(100), SomeNameA VARCHAR(100))
CREATE TABLE Tableb (Email VARCHAR(100), SomeNameB VARCHAR(100))
CREATE TABLE Tablec (Email VARCHAR(100), SomeNameC VARCHAR(100))

INSERT INTO TableA SELECT 'joe@test.com', 'JoeA'
INSERT INTO TableA SELECT 'jan@test.com', 'JaneA'
INSERT INTO TableA SELECT 'dave@test.com', 'DaveA'
INSERT INTO TableB SELECT 'joe@test.com', 'JoeB'
INSERT INTO TableB SELECT 'dave@test.com', 'DaveB'
INSERT INTO TableC SELECT 'joe@test.com', 'JoeC'
INSERT INTO TableC SELECT 'dave@test.com', 'DaveC'


SELECT TOP 2 a.*,
             b.*,
             c.*
FROM   TableA a
       LEFT OUTER JOIN TableB b
                    ON a.email = b.email
       INNER JOIN TableC c
                    ON c.Email = b.email;

SELECT TOP 2 a.*,
             b.*,
             c.*
FROM   TableA a
       LEFT OUTER JOIN TableB b
       INNER JOIN TableC c
                    ON c.Email = b.email
                    ON a.email = b.email;

我不明白为什么这两个SELECT语句会产生不同的结果。

2 个答案:

答案 0 :(得分:12)

重要的是连接顺序。将表达式视为每个连接都产生临时“虚拟”表。

所以当你写

FROM TableA a 
LEFT OUTER JOIN TableB b ON a.email = b.email
INNER JOIN TableC c ON c.Email = b.email ;

然后订单如下:

  1. TableA与[{1}}联系,产生临时关系TableB
  2. V1内部加入了V1
  3. 写作时的意思是:

    TableC

    然后订单如下:

    1. FROM TableA a LEFT OUTER JOIN TableB b INNER JOIN TableC c ON c.Email = b.email ON a.email = b.email; TableB内部联系,产生临时关系TableC
    2. V1已加入TableA
    3. 因此结果不同。通常建议在这种情况下使用括号来提高查询的可读性:

      V1

答案 1 :(得分:4)

在第二个示例中,ON a.email = b.email部分属于LEFT JOIN 如果这样写,则表示以下内容:

INNER JOIN TableC与TableB和LEFT OUTER JOIN结果与TableA。

结果将是TableA中的所有行与TableB中的那些行连接,这些行在TableC中也有一个条目。

第一个例子意味着以下内容:

LEFT OUTER JOIN TableB与TableA和INNER JOIN TableC与结果。这相当于对TableB使用INNER JOIN 说明:当您使用TableB LEFT OUTER JOIN TableA时,您将获得TableA中的所有行,并且对于TableB中的匹配行,您也将获得该数据。在结果集中,您将拥有b.email = NULL的行,现在将使用TableC INNER JOIN。只要TableC中没有email = NULL的条目,您就会得到您观察到的结果。