首页 > 解决方案 > 左连接与堆叠左连接

问题描述

我想问一下这两个查询有什么区别:

SELECT 
    Customers.CustomerID, Customers.CustomerName, Orders.OrderID, 
    OrderDetails.Quantity, Products.ProductName
FROM
    Customers
LEFT JOIN 
    (Orders 
LEFT JOIN  
    (OrderDetails 
LEFT JOIN 
    Products ON Products.ProductID = OrderDetails.ProductID
    ) ON OrderDetails.OrderID = Orders.OrderID
  ) ON Customers.CustomerID = Orders.CustomerID
GROUP BY 
    Customers.CustomerName;

VS

SELECT 
    Customers.CustomerID, Customers.CustomerName, Orders.OrderID, 
    OrderDetails.Quantity, Products.ProductName
FROM 
    Customers
LEFT JOIN 
    Orders ON Orders.CustomerID = Customers.CustomerID
LEFT JOIN 
    OrderDetails ON OrderDetails.OrderID = Orders.OrderID
LEFT JOIN 
    Products ON Products.ProductID = OrderDetails.ProductID
GROUP BY 
    Customers.CustomerName;

在这里测试 https://www.w3schools.com/sql/trysql.asp?filename=trysql_select_join

从我可以看到一个选择多个条目中的第一个,一个选择多个条目中的最后一个,但这就是全部吗?

从我的角度来看,非嵌套的 LEFT Join 更容易阅读和理解。使用它有什么缺点吗?

标签: sqljoinnested

解决方案


您的问题是错误使用GROUP BY. 中唯一未聚合的列SELECT应该在GROUP BY.

这个答案的其余部分解决了关于连接的问题。

您的第二个查询被解释为:

FROM (((Customers c LEFT JOIN
        Orders o
        ON o.CustomerID = c.CustomerID
       ) LEFT JOIN
       OrderDetails 
       ON od.OrderID = o.OrderID
      ) LEFT JOIN
      Products p
      ON p.ProductID = od.ProductID

括号会影响解释。但是有什么作用呢?本质上,你有:

(((c left join o) left join od) left join p)

相对

c left join (o left join (od left join p)))

两者都将所有记录保存在 中c,无论第二个中的匹配如何。在这种情况下,两个版本做同样的事情。但是由于一个特殊的原因——on条件是严格链接的(即,c 到 o,o 到 od,od 到 p)。如果p加入 whereo而不是od,则可能会出现细微的差异。

有哪些细微差别?有两件事可以不同:

  • 特定表中的列是否存在NULL或具有值。
  • 由于两个表之间的多次匹配,行是否重复。

在实践中,我对细括号并不特别有用。如果可以JOIN订购,我会使用显式子查询或 CTE>


推荐阅读