【问题标题】:Is it true that all joins following a left join in a SQL query must also be left joins? Why or why not?SQL查询中左连接之后的所有连接是否也必须是左连接?为什么或者为什么不?
【发布时间】:2018-12-13 16:32:51
【问题描述】:

我记得大学时的一条经验法则,如果您在 SQL 查询中放置左连接,那么该查询中的所有后续连接也必须是左连接而不是内连接,否则您会得到意想不到的结果.但我不记得这些结果是什么,所以我想知道我是否记错了什么。任何人都可以支持我或反驳它吗?谢谢! :)

例如:

select * from customer
left join ledger on customer.id= ledger.customerid
inner join order on ledger.orderid = order.id -- this inner join might be bad mojo

【问题讨论】:

  • 您最好告诉我们您使用的是什么 RDBMS,因为它们在允许和不允许的方面有所不同。 “意外结果”对我来说似乎很可疑,但它很可能再次取决于(而且几乎肯定是)数据库。
  • 我主要使用 SQL Server。
  • "...否则您会得到意想不到的结果...":除非您知道自己在做什么,并且会给出结果期待。

标签: sql


【解决方案1】:

不是他们必须是。他们应该是(或者最后可能是full join)。这是编写查询和表达逻辑的更安全的方式。

您的查询是:

select *
from customer c left join
     ledger l
     on c.id = l.customerid inner join
     order o 
     on l.orderid = o.id 

left join 说“保留所有客户,即使 ledger 中没有匹配记录。第二个说,“我必须有一个匹配的分类帐记录”。所以,inner join 将第一个转换为inner join

因为您大概想要所有客户,无论其他两个表中是否存在匹配项,您都将使用left join

select *
from customer c left join
     ledger l
     on c.id = l.customerid left join
     order o 
     on l.orderid = o.id 

【讨论】:

    【解决方案2】:

    你没记错其中的某些部分!

    问题是,当您像这样链接连接表时

    select * from customer
    left join ledger on customer.id= ledger.customerid
    inner join order on ledger.orderid = order.id
    

    JOIN 是按顺序执行的,所以当customer left join ledger 发生时,您要确保所有来自客户返回的连接键(因为它是左连接!并且您将客户放置在左侧)。

    接下来,

    前 JOIN 的结果与 order 连接(使用内部连接),强制“第一个连接键”与来自 order 的键匹配(1 到 1),所以你最终只会得到order 表中也匹配的记录

    坏魔力?这实际上取决于您要完成的工作。
    如果你想保证来自customers的所有记录都返回,你应该保持“左加入”它。

    但是,您可以通过以下方式使其更直观地理解(不一定是更好的 SQL 编写方式!):

        SELECT * FROM 
    
        (
          (SELECT * from customer) c
    
        LEFT JOIN
    
         (SELECT * from ledger) l
    
        ON
           c.id= l.customerid
        ) c_and_l
    
        INNER JOIN (OR PERHAPS LEFT JOIN)
    
    (SELECT * FROM order) as o
    
        ON c_and_l.orderid (better use c_and_l.id as you want to refer to customerid from customers table) = o.id
    

    所以现在你明白了 c_and_l 是先创建的,然后加入到 order 中(你可以把它想象成 2 个表再次加入)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-07-08
      • 2010-09-30
      • 2012-01-03
      • 2015-10-18
      • 1970-01-01
      • 1970-01-01
      • 2013-03-24
      • 2012-09-28
      相关资源
      最近更新 更多