协慌网

登录 贡献 社区

SQL JOIN-WHERE 子句与 ON 子句

阅读后,这不是Explicit 与 Implicit SQL Joins的重复。答案可能是相关的(甚至是相同的),但问题是不同的。


有什么区别,每个应该有什么区别?

如果我正确理解该理论,则查询优化器应该可以互换使用。

答案

它们不是同一件事。

考虑以下查询:

SELECT *
FROM Orders
LEFT JOIN OrderLines ON OrderLines.OrderID=Orders.ID
WHERE Orders.ID = 12345

SELECT *
FROM Orders
LEFT JOIN OrderLines ON OrderLines.OrderID=Orders.ID 
    AND Orders.ID = 12345

第一个将返回订单及其订单号为12345行(如果有)。第二个将返回所有订单,但是只有订单12345会与之关联任何行。

使用INNER JOIN ,这些子句实际上是等效的。但是,仅仅因为它们在功能上相同而产生相同的结果,并不意味着这两种子句具有相同的语义。

  • 内连接无关紧要

  • 外连接事项

    一种。 WHERE子句:加入之后。加入后将过滤记录。

    b。 ON子句 - 加入之前。记录(来自右表)将在加入之前被过滤。结果可能为空(因为 OUTER 连接)。



示例:考虑下表:

1. documents:
     | id    | name        |
     --------|-------------|
     | 1     | Document1   |
     | 2     | Document2   |
     | 3     | Document3   |
     | 4     | Document4   |
     | 5     | Document5   |


    2. downloads:
     | id   | document_id   | username |
     |------|---------------|----------|
     | 1    | 1             | sandeep  |
     | 2    | 1             | simi     |
     | 3    | 2             | sandeep  |
     | 4    | 2             | reya     |
     | 5    | 3             | simi     |

a)在WHERE子句中:

SELECT documents.name, downloads.id
    FROM documents
    LEFT OUTER JOIN downloads
      ON documents.id = downloads.document_id
    WHERE username = 'sandeep'

 For above query the intermediate join table will look like this.

    | id(from documents) | name         | id (from downloads) | document_id | username |
    |--------------------|--------------|---------------------|-------------|----------|
    | 1                  | Document1    | 1                   | 1           | sandeep  |
    | 1                  | Document1    | 2                   | 1           | simi     |
    | 2                  | Document2    | 3                   | 2           | sandeep  |
    | 2                  | Document2    | 4                   | 2           | reya     |
    | 3                  | Document3    | 5                   | 3           | simi     |
    | 4                  | Document4    | NULL                | NULL        | NULL     |
    | 5                  | Document5    | NULL                | NULL        | NULL     |

  After applying the `WHERE` clause and selecting the listed attributes, the result will be: 

   | name         | id |
   |--------------|----|
   | Document1    | 1  |
   | Document2    | 3  |

b)在JOIN子句中

SELECT documents.name, downloads.id
  FROM documents
    LEFT OUTER JOIN downloads
      ON documents.id = downloads.document_id
        AND username = 'sandeep'

For above query the intermediate join table will look like this.

    | id(from documents) | name         | id (from downloads) | document_id | username |
    |--------------------|--------------|---------------------|-------------|----------|
    | 1                  | Document1    | 1                   | 1           | sandeep  |
    | 2                  | Document2    | 3                   | 2           | sandeep  |
    | 3                  | Document3    | NULL                | NULL        | NULL     |
    | 4                  | Document4    | NULL                | NULL        | NULL     |
    | 5                  | Document5    | NULL                | NULL        | NULL     |

Notice how the rows in `documents` that did not match both the conditions are populated with `NULL` values.

After Selecting the listed attributes, the result will be: 

   | name       | id   |
   |------------|------|
   |  Document1 | 1    |
   |  Document2 | 3    | 
   |  Document3 | NULL |
   |  Document4 | NULL | 
   |  Document5 | NULL |

INNER JOIN它们是可互换的,优化器将随意重新排列它们。

OUTER JOIN ,它们不一定是可互换的,这取决于它们所依赖的联接的哪一侧。

我根据可读性将它们放在任何一个地方。