2

我目前正在阅读一个在加入表时通常不会在其他一些查询中看到的查询。

SELECT 
    *
FROM table_1 
    RIGHT OUTER JOIN table_2 
    INNER JOIN table_3 
        ON table_2.some_id = table_3.some_id
    RIGHT OUTER JOIN table_4 
        ON table_3.some_id = table_4.some_id 
    LEFT OUTER JOIN table_5 
        ON table_4.some_id = table_5.some_id 
        ON table_1.some_id = table_4.some_id

请不要介意这些表是如何连接的。我只想知道该查询是如何工作的?先感谢您。

4

2 回答 2

3

我认为 SQL Server 文档比 MySQL 更能捕捉到正在发生的事情。(这里是文档。)

正如 Laurence 所观察到的,这是一个解析问题。您可以通过查看语句的语法图来了解它的含义from。有一个大多数人(包括我)从未想过的递归引用。连接表具有以下语法:

<joined_table> ::= 
{
    <table_source> <join_type> <table_source> ON <search_condition> 
    | <table_source> CROSS JOIN <table_source> 
    | left_table_source { CROSS | OUTER } APPLY right_table_source 
    | [ ( ] <joined_table> [ ) ] 
}

这里的关键是第一部分,<table_source> <join_type> <table_source>. 好吧,你猜怎么着,atable_source可以是 a joined_table(以及一堆其他的东西)。这意味着语法:

A join B join C ON <condition1> ON <condition2>

符合上面的语法并被解释为:

A join (B join C on <condition1>) ON <condition2>

也就是说,表达式B join C on <condition1>被视为“table_source”。

我的猜测是,如果 SQL Server 和 MySQL 都这样做,那么它可能是标准的一部分。但是,该标准比 SQL Server 的语法图更难理解。

于 2013-11-04T00:52:05.027 回答
2

我认为这取决于评估右外连接的方式:

Select
  * 
from 
  a
    right outer join 
  b
    inner join
  c 
    on b.id = c.id 
    on a.id = b.id;

被评估为

Select
  * 
from 
  a
    right outer join (
  b
    inner join
  c 
    on b.id = c.id 
  )
    on a.id = b.id;

混合左外连接和右外连接是一条疯狂的道路。

OP 的查询似乎是由排除括号或派生表的愿望驱动的。它相当于:

Select
    a.id ida,
    b.id idb,
    c.id idc,
    d.id idd,
    e.id ide
From
    D
        left outer join
    A
        on d.id = a.id
        left outer join
    E
        on d.id = e.id
        left outer join (
    B
        inner join
    C
        on b.id = c.id
    ) 
        on d.id = b.id;

Example SQLFiddle

于 2013-11-04T00:43:55.767 回答