左联接vs堆叠左联接

时间:2018-08-21 10:13:33

标签: sql join nested

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

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比较容易阅读和理解。使用它有什么缺点吗?

1 个答案:

答案 0 :(得分:0)

您的问题是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加入了o而不是od,那么可能会产生细微的差异。

细微的区别是什么?两件事可能有所不同:

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

在实践中,我不使用括号特别有用。如果可以处理JOIN的订单,请使用显式子查询或CTE>