INNER JOIN和LEFT / RIGHT OUTER JOIN的问题

我有三个表格:

  • 命令
  • OrderId,int PK
  • CustomerId,int FK到Customer,允许NULL

  • 顾客
  • CustomerId,int PK
  • CompanyId,int FK给公司,NULL不允许

  • 公司
  • CompanyId,int PK
  • 名称,nvarchar(50)
  • 我想选择所有订单,不管他们是否有客户,如果他们有客户,那么客户的公司名称也是如此。

    如果我使用这个查询...

    SELECT Orders.OrderId, Customers.CustomerId, Companies.Name
    FROM   Orders
           LEFT OUTER JOIN Customers
               ON Orders.CustomerId = Customers.CustomerId
           INNER JOIN Companies
               OM Customers.CompanyId = Companies.CompanyId
    

    ...它只返回有客户的订单。 如果我用LEFT OUTER JOIN替换INNER JOIN LEFT OUTER JOIN ...

    SELECT Orders.OrderId, Customers.CustomerId, Companies.Name
    FROM   Orders
           LEFT OUTER JOIN Customers
               ON Orders.CustomerId = Customers.CustomerId
           LEFT OUTER JOIN Companies
               OM Customers.CompanyId = Companies.CompanyId
    

    ...它可行,但我不明白为什么这是必要的,因为CustomersCompanies之间的关系是必需的:客户必须有一个公司。

    另一种可行的方法似乎是:

    SELECT Orders.OrderId, Customers.CustomerId, Companies.Name
    FROM   Companies
           INNER JOIN Customers
               ON Companies.CompanyId = Customers.CompanyId
           RIGHT OUTER JOIN Orders
               OM Customers.CustomerId Orders.CustomerId
    

    此查询具有我期望的内连接和外连接的数量,但问题是难以阅读,因为我的查询是作为查询订单的,因此订单是选择的“根”,而不是公司。 另外RIGHT OUTER JOIN的使用对我来说也是不熟悉的。

    最后一个查询是由设计人员为SQL Server Reporting Services报表生成的查询的一小部分。 我试图在没有设计器表面的情况下手动编写查询,因为它非常拥挤,而且在将来需要进行很多更改和更多更改之后,我仍然遇到问题以维护查询。 所以,我想以某种方式给查询一个可读结构。

    问题:

  • 为什么不按照我的预期查询1?
  • 查询2是正确的解决方案,但(因为?)它使用两个左其他连接?
  • 查询3是否是正确的解决方案?
  • 有没有更好的方法来编写查询?
  • 有没有一些一般的经验法则和实践如何编写一个有很多外部和内部联接的查询,并且可读性好?

  • 在语义上,连接按照它们出现在from子句中的顺序进行处理。 (由于SQL优化,它们可能不会按此顺序实际执行,但排序对于定义结果集很重要。)

    所以,当你这样做时:

    from orders left outer join customers inner join companies
    

    (我要离开了on条款这些都是为此分心。)

    SQL被解释为:

    from (orders left outer join customers) inner join companies
    

    你正在做一个inner join ,所以这些值必须出现在两边。 在你的情况下,这撤消了left outer join的效果。

    你要:

    from orders left outer join (customers inner join companies)
    

    这里有一些解决方案。

    我的首选解决方案是对所有连接使用left outer join连接。 事实上,为了可读性和可维护性,我写的几乎每个查询都只是left outer join[inner] join连接表。 如果能够以一致的形式编写查询,则必须解析查询以了解连接的语义,这似乎是不必要的努力。

    另一种解决方案是使用括号:

    from orders left outer join (customers inner join companies)
    

    另一个解决方案是子查询:

    from orders left outer join (select . . . from customers inner join companies) cc
    

  • 查询1:因为你在客户上有INNER JOIN ,所以LEFT JOIN实际上是一个INNER JOIN
  • 查询2是正确的,因为无论数据质量/条件如何,您都希望看到所有订单。
  • 我喜欢避免使用RIGHT JOIN ,因为它会让一些开发人员感到困惑,因此不易读。 您通常可以用这种方式编写查询,以便有效使用LEFT JOIN做同样的事情。
  • 查询2是我对这样简单的建议。
  • 一个一般的规则......一旦你引入一个OUTER JOIN到你的查询,在JOIN后面也应作为s OUTER JOIN秒。 否则,您可以排除您不想要的行。

  • 您可以编写像这样嵌套的连接,以便在客户和公司的组合结果上执行左连接,而不是在订单和客户的组合结果上执行内连接。 我基本上只是将你的内连接移动到左外连接的ON子句之前。 其他人建议括号来获得这个结果,如果内存服务的话,两种语法都会导致相同的执行。

    SELECT Orders.OrderId, Customers.CustomerId, Companies.Name
    FROM   Orders
    LEFT OUTER JOIN Customers
        INNER JOIN Companies
            ON Customers.CompanyId = Companies.CompanyId
        ON Orders.CustomerId = Customers.CustomerId
    
    链接地址: http://www.djcxy.com/p/86291.html

    上一篇: Problems with INNER JOIN and LEFT/RIGHT OUTER JOIN

    下一篇: CASE is not working in SQL Server