【问题标题】:Do I have to do a LEFT JOIN after a RIGHT JOIN?我必须在右连接后进行左连接吗?
【发布时间】:2012-12-21 22:24:10
【问题描述】:

假设我在 SQL Server 2008 R2 中有三个表

SELECT a.*, b.*, c.*
FROM
  Table_A a
  RIGHT JOIN Table_B b ON a.id = b.id
  LEFT JOIN Table_C c ON b.id = c.id

SELECT a.*, b.*, c.*
FROM
  Table_A a
  RIGHT JOIN Table_B b ON a.id = b.id
  JOIN Table_C c ON b.id = c.id

另外,我在加入 c 时使用 b.id 还是 a.id 有关系吗?

即而不是JOIN Table_C c ON b.id = c.id,使用JOIN Table_C c ON a.id = c.id

谢谢!

【问题讨论】:

  • 不,您不必在右连接后进行左连接;您可以在第一个 RIGHT JOIN 之后执行 INNER JOIN 或另一个 RIGHT JOIN。是的,一般来说,加入什么很重要。
  • 不,你错了。右连接后需要左连接。看我的回答。
  • 在语法上,根据 SQL 标准,没有限制必须在 RIGHT JOIN 之后执行 LEFT JOIN。要使用一组特定的表来制定特定的查询,您可能需要在 RIGHT JOIN 之后执行 LEFT JOIN,但这是特定查询的属性,而不是 SQL 语法的属性。您将能够重新排序查询中的术语。你必须小心你加入哪些列。
  • 有趣的是,当你的孩子问你下雨时他是否必须打开雨伞而你说不时,你的回答很有趣,没有限制下雨时必须打开雨伞。那么首先使用雨伞有什么意义呢?对不起,是的,你是对的,但我无法从你的回答中得到任何信息。
  • 您的问题中缺少关于您希望保留 Table_B 中的 all 行的部分。如果添加它会更有意义,因为答案是“是的,你需要外部加入 Table_C”,否则答案是“这取决于你想要的结果”。

标签: sql sql-server-2008 join outer-join


【解决方案1】:

是的,在右连接之后确实需要左连接

http://sqlfiddle.com/#!3/2c079/5/0

http://sqlfiddle.com/#!3/2c079/6/0

如果你不这样做,最后的(内部)JOIN 将抵消你的 RIGHT JOIN 的效果。

如果您不在乎,那么进行 RIGHT JOIN 是没有任何意义的。如果你关心的话,你必须在它之后添加一个 LEFT JOIN。

【讨论】:

  • 这取决于你想要什么结果。 inner join 版本不会像你说的那样“取消”right join。如果right join 被您使用的inner join 取消,您将得到两行而不是三行SQL Fiddle
  • 它不会取消 RIGHT JOIN,它只会产生不同的结果。您将加入cb,而不是a。如果您的示例中没有a,并且将b left join cb inner join c 进行比较,您会得到相同的结果差异。也许,您打算使用不同的示例。
  • 使用 RIGHT JOIN 的唯一原因是因为我想'返回右表中的所有行,即使左表中没有匹配项',这是在谈论 a 到 b。现在为了保持该语句的正确性,在 RIGHT JOIN 之后必须有一个 LEFT JOIN,否则我得到的行数会更少。
  • 对 Andriy,不,我不会将 c 加入 b。如果我是,你是对的,我根本不需要左连接,因为 b 的 id 比 c 多。我将 c 加入 (a RIGHT JOIN b) 的结果表和 INNER JOIN 更改我的表 (a RIGHT JOIN b),这意味着必须使用 LEFT JOIN 才能不更改我的表 (a RIGHT JOIN b) .
  • 是的,当我看到你的回复时,我正要纠正我的错误。你是对的,第三个表连接到连接的结果,而不是严格地连接到第二个表。但是,连接条件不引用 a 列。这意味着最后一次连接的结果不依赖于a,这意味着它们不会取消正确连接的效果。
【解决方案2】:

根据定义:

  • 加入 : 当两个表中至少有一个匹配时返回行
  • LEFT JOIN返回左表中的所有行,即使右表中没有匹配项
  • RIGHT JOIN返回右表中的所有行,即使左表中没有匹配项

第一个选项将包括来自表 ab 的第一个连接的所有原始数据,即使表 c 中没有匹配的原始数据,而第二个语句将仅显示与表 @ 中的原始数据匹配的原始数据987654324@.

关于第二个问题,我想这会有所不同,因为第一个连接包括表 b 中的所有 ids,即使表 a 中没有匹配的,所以一旦你更改了 Join creterium到a.id 你会得到一组不同于b.id 的ID。

【讨论】:

    【解决方案3】:

    如果它不改变查询的语义,数据库服务器可以重新排序连接,以它认为更有效的方式运行。

    通常,如果要强制某个顺序,可以使用内联视图子查询,如

    SELECT a.*, x.*
    FROM
      Table_A a
      RIGHT JOIN
      (
        SELECT *, b.id as id2 FROM Table_B b 
        LEFT JOIN Table_C c ON b.id = c.id
      ) x
      ON a.id = x.id2
    

    【讨论】:

    • 谢谢。不,我不想要任何顺序,只是担心右连接后的内连接会抵消右连接效果。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-07-28
    • 1970-01-01
    • 1970-01-01
    • 2015-01-11
    • 2015-07-17
    • 1970-01-01
    相关资源
    最近更新 更多