SQL用两个过滤的列联接查询一行

时间:2018-09-16 23:51:11

标签: sql-server tsql join

我正在使用WorldWideImporters Microsoft示例数据库表。我想返回的客户行中的各列将显示其2014年,2015年的总销售额,并在各自的列中分别显示两者的总和。我不允许使用任何形式的subqueries

对于这个问题,我正在尝试这样解决:

SELECT C.CustomerID
      ,C.CustomerName
      ,ISNULL(SUM(OL.Quantity * OL.UnitPrice), 0.00) AS [2014Sales]
      ,ISNULL(SUM(OLP.Quantity * OLP.UnitPrice), 0.00) AS [2015Sales]
      ,ISNULL(SUM(OL.Quantity * OL.UnitPrice), 0.00)
       + ISNULL(SUM(OLP.Quantity * OLP.UnitPrice), 0.00) AS [TotalSales]
FROM Sales.Customers AS C 
LEFT OUTER JOIN Sales.Orders AS O ON C.CustomerID = O.CustomerID
AND O.OrderDate BETWEEN '2014-01-01' AND '2014-12-31'
LEFT OUTER JOIN Sales.OrderLines AS OL ON O.OrderID = OL.OrderID
LEFT OUTER JOIN Sales.Orders AS OP ON O.CustomerID = C.CustomerID
AND O.OrderDate BETWEEN '2015-01-01' AND '2015-12-31'
LEFT OUTER JOIN Sales.OrderLines AS OLP ON OL.OrderID = O.OrderID
GROUP BY C.CustomerID
        ,C.CustomerName
ORDER BY TotalSales DESC, CustomerID;

我很难理解加入。我是从具有一些面向对象的经验而来的,我无法完全围绕关系联接工作。我可以看到如何通过子查询来解决此问题,一个子查询用于2015年,一个子查询用于2014年。

就目前而言,我的查询不断地运行,这意味着我尝试加入两次的方式必须尝试合并太多的行组合。任何帮助解释这里发生了什么以及如何解决我的查询的帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

在编辑查询时,有些行没有意义:

您加入了相同的表,而没有在ON语句中指出它们的条件。

请注意,您分别命名了Sales.OrdersSales.OrderLines OPOLP,但仍使用标准O.CustomerID = C.CustomerIDOL.OrderID = O.OrderID

LEFT OUTER JOIN Sales.OrderLines AS OL ON O.OrderID = OL.OrderID
LEFT OUTER JOIN Sales.Orders AS OP ON O.CustomerID = C.CustomerID
AND O.OrderDate BETWEEN '2015-01-01' AND '2015-12-31'
LEFT OUTER JOIN Sales.OrderLines AS OLP ON OL.OrderID = O.OrderID

看看是否可行:我刚刚更正了您的加入条件。

SELECT C.CustomerID
      ,C.CustomerName
      ,ISNULL(SUM(OL.Quantity * OL.UnitPrice), 0.00) AS [2014Sales]
      ,ISNULL(SUM(OLP.Quantity * OLP.UnitPrice), 0.00) AS [2015Sales]
      ,ISNULL(SUM(OL.Quantity * OL.UnitPrice), 0.00)
       + ISNULL(SUM(OLP.Quantity * OLP.UnitPrice), 0.00) AS [TotalSales]
FROM Sales.Customers AS C 
LEFT OUTER JOIN Sales.Orders AS O ON C.CustomerID = O.CustomerID
                                  AND CONVERT(date, O.OrderDate) BETWEEN '2014-01-01' AND '2014-12-31'
LEFT OUTER JOIN Sales.OrderLines AS OL ON O.OrderID = OL.OrderID
LEFT OUTER JOIN Sales.Orders AS OP ON C.CustomerID = OP.CustomerID
                                   AND CONVERT(date, OP.OrderDate) BETWEEN '2015-01-01' AND '2015-12-31'
LEFT OUTER JOIN Sales.OrderLines AS OLP ON OP.OrderID = OLP.OrderID 
GROUP BY C.CustomerID
        ,C.CustomerName
ORDER BY [TotalSales] DESC, CustomerID;

我还向日期字段添加了CONVERT(date,以忽略时间部分。

编辑:

如果不使用subquery,我认为这将无效。所以我就把它留在这里,以防您已经可以使用它。

SELECT [2014].CustomerID
      ,[2014].CustomerName
      ,[2014Sales]
      ,[2015Sales]
      ,[2014Sales] + [2015Sales] AS [TotalSales]
FROM (
    (SELECT C.CustomerID
           ,C.CustomerName
           ,ISNULL(SUM(OL.Quantity * OL.UnitPrice), 0.00) AS [2014Sales]
     FROM Sales.Customers AS C 
     LEFT OUTER JOIN Sales.Orders AS O ON C.CustomerID = O.CustomerID
     LEFT OUTER JOIN Sales.OrderLines AS OL ON O.OrderID = OL.OrderID
     WHERE O.OrderDate BETWEEN '2014-01-01' AND '2014-12-31'
     GROUP BY C.CustomerID
             ,C.CustomerName) AS [2014]
LEFT OUTER JOIN
    (SELECT C2.CustomerID
           ,C2.CustomerName
           ,ISNULL(SUM(OLP.Quantity * OLP.UnitPrice), 0.00) AS [2015Sales]
     FROM Sales.Customers AS C2
     LEFT OUTER JOIN Sales.Orders AS OP ON OP.CustomerID = C2.CustomerID
     LEFT OUTER JOIN Sales.OrderLines AS OLP ON OP.OrderID = OLP.OrderID
     WHERE OP.OrderDate BETWEEN '2015-01-01' AND '2015-12-31'
     GROUP BY C2.CustomerID
             ,C2.CustomerName) AS [2015] ON [2014].CustomerID = [2015].CustomerId
ORDER BY [2014Sales] + [2015Sales] DESC, CustomerID;