代码之家  ›  专栏  ›  技术社区  ›  vulkanino

SQL连接三个表,连接优先级

sql
  •  20
  • vulkanino  · 技术社区  · 14 年前

    我有三张桌子:R、S和P。

    应该 在S中至少有一个记录,以便我可以加入:

    SELECT
            *
        FROM 
            R
        JOIN    S ON (S.id = R.fks)
    

    如果s中没有记录,那么我就没有行,这很好。

    然后表S与P连接,其中记录为P可能存在也可能不存在,并与S连接。

    我也是

    SELECT
            *
        FROM 
            R
        JOIN    S ON (S.id = R.fks)
        LEFT JOIN P ON (P.id = S.fkp)
    

    如果我想让第二个连接绑定到S而不是R,比如我可以使用括号:

    SELECT
            *
        FROM 
            R
        JOIN    (S ON (S.id = R.fks) JOIN P ON (P.id = S.fkp))
    

    或者这已经是R,S和P之间笛卡尔积的自然行为了?

    4 回复  |  直到 14 年前
        1
  •  50
  •   rakslice    3 年前

    所有类型的外部联接和普通联接都在同一个优先级类中,运算符在查询的给定嵌套级别从左到右生效。您可以将连接表达式放在右括号中,使其首先生效。记住,你必须移动 ON 括号后面的子句。

    (PostgreSQL示例)

    SELECT * FROM a LEFT JOIN b ON (a.id = b.id) JOIN c ON (b.ref = c.id);

    SELECT * FROM a LEFT JOIN (b JOIN c ON (b.ref = c.id)) ON (a.id = b.id);

    通常,您可以通过移动连接并更改外部连接方向来表达相同的内容,而不需要额外的括号,例如。

    SELECT * FROM b JOIN c ON (b.ref = c.id) RIGHT JOIN a ON (a.id = b.id);

        2
  •  3
  •   Andrew Carmichael    14 年前

    当您加入第三个表时,您的第一个查询

    SELECT
            *
        FROM 
            R
        JOIN    S ON (S.id = R.fks)
    

    类似于一个派生表,您要将第三个表加入其中。所以如果 R JOIN S 不生成行,然后合并 P 永远不会产生任何行(因为您正试图连接到一个空表)。

    所以,如果你在寻找优先规则,那么在这种情况下,它只是通过使用 LEFT JOIN 相对于 JOIN

    不过,我可能误解了你的问题,因为如果我写的是查询,我会交换 S R 周围。如。

    SELECT
            *
        FROM 
            S
        JOIN    R ON (S.id = R.fks)
    
        3
  •  2
  •   El Ronnoco    14 年前

    第二个连接 当你明确地说 JOIN P ON (P.id = S.fkp)

        4
  •  -1
  •   Stuart Steedman    8 年前
    with a as (select 1 as test union select 2)
    select * from a left join
    a as b on a.test=b.test and b.test=1 inner join
    a as c on b.test=c.test 
    go
    with a as (select 1 as test union select 2)
    select * from a inner join
    a as b on a.test=b.test  right join
    a as c on b.test=c.test and b.test=1
    

    理想情况下,我们希望上述两个查询是相同的。然而,事实并非如此,所以任何人说右连接可以用左连接代替,在任何情况下都是错误的。只有使用正确的连接才能得到所需的结果。