SQL Subtotal和Grand Totals

时间:2014-02-02 21:31:14

标签: sql sql-server

我的代码是否可以解决以下问题? 1996年7月订购的所有订单的总成本。查看2个表(OrdersOrderDetails)这是我到目前为止所做的。

SELECT     
   Orders.OrderID, Customers.ContactName, Orders.OrderDate
FROM       
   Customers 
INNER JOIN
   Orders ON Customers.CustomerID = Orders.CustomerID 
INNER JOIN
   [Order Details] ON Orders.OrderID = [Order Details].OrderID
WHERE     
   (Orders.OrderDate BETWEEN CONVERT(DATETIME, '1996-07-01 00:00:00', 102) AND CONVERT(DATETIME, '1996-07-31 00:00:00', 102))
   AND SUM(Quantity * UnitPrice) AS grand_total;

目的是找到每一行的总和并保留该数字,然后对行进行求和以产生总计。当我运行查询时,它肯定不会产生应该是什么。

3 个答案:

答案 0 :(得分:2)

试试这个:

SELECT     
   o.OrderID, c.ContactName, o.OrderDate, SUM(od.Quantity * od.UnitPrice) AS grand_total
FROM       
   dbo.Customers c 
INNER JOIN
   dbo.Orders o ON c.CustomerID = o.CustomerID 
INNER JOIN
   dbo.[Order Details] od ON o.OrderID = od.OrderID
WHERE     
   o.OrderDate BETWEEN {ts '1996-07-01 00:00:00.000'} AND {ts '1996-07-31 23:59:59.997'}
GROUP BY 
   GROUPING SETS ((o.OrderID, c.ContactName, o.OrderDate), ())

GROUPING SETS ((o.OrderID, c.ContactName, o.OrderDate), ...)会按o.OrderID, c.ContactName, o.OrderDate对源行进行分组,并且还会计算每SUM个值对的OrderID, ContactName, OrderDate

GROUPING SETS ((...), ())指示SQL Server计算总计(所有订单总计的总和):

SELECT OrderID, SUM(OrderDetailValue) AS OrderTotal
FROM (
    SELECT 11, 1, 'A', 1 UNION ALL 
    SELECT 12, 1, 'B', 10 UNION ALL 
    SELECT 13, 2, 'A', 100
) AS Orders(OrderDetailID, OrderID, ProductName, OrderDetailValue)
GROUP BY GROUPING SETS ((OrderID), ());

结果:

OrderID OrderTotal
------- ----------
1       11  <-- Total generated by GROUPING SETS ((OrderID), ...)
2       100 <-- Total generated by GROUPING SETS ((OrderID), ...)
NULL    111 <-- Total generated by GROUPING SETS (..., ())

答案 1 :(得分:1)

有很多方法可以做到这一点。

GROUP BY ROLLUP - http://technet.microsoft.com/en-us/library/ms177673.aspx

分组集 - http://technet.microsoft.com/en-us/library/bb522495(v=SQL.105).aspx

OVER - http://technet.microsoft.com/en-us/library/ms189461.aspx

不要使用Shiva的解决方案,因为COMPUTE在SQL Server 2012中已经不存在了!

以下是我在解决方案中纠正的一些问题。

1 - Use table alias's
2 - Do not use between or convert on date ranges.  
    It will not be SARGABLE.

由于您并非具体,因此无论订单ID如何,我都会根据客户订单ID选择一个简单的总和,其中包含客户的总月份。

为了解决这个问题,我使用了OVER子句。由于我没有您的测试数据或表格,因此检查解决方案是否存在语法错误是您的作业。

-- Customer sum by order id, total sum by customer.
SELECT 
  C.ContactName, 
  O.OrderID, 
  O.OrderDate, 
  SUM(D.Quantity * D.UnitPrice) AS OrderTotal, 
  SUM(D.Quantity * D.UnitPrice) OVER (PARTITION BY C.ContactName) as CustomerTotal
FROM Customers as c INNER JOIN Orders as O
  ON C.CustomerID = O.CustomerID 
INNER JOIN [Order Details] D 
  ON O.OrderID = D.OrderID 
WHERE 
  O.OrderDate >= '1996-07-01 00:00:00' AND 
  O.OrderDate < '1996-08-01 00:00:00'
GROUP BY
  C.ContactName,
  O.OrderID, 
  O.OrderDate 

答案 2 :(得分:0)

;WITH CTE
AS(
SELECT     Orders.OrderID
         , Customers.ContactName
         , Orders.OrderDate
         , SUM(Quantity * UnitPrice) AS grand_total
         , rn = ROW_NUMBER() OVER (ORDER BY Orders.OrderID)
FROM       Customers INNER JOIN
           Orders ON Customers.CustomerID = Orders.CustomerID INNER JOIN
           [Order Details] ON Orders.OrderID = [Order Details].OrderID
WHERE MONTH(Orders.OrderDate) = 7 AND  YEAR(Orders.OrderDate) = 1996
GROUP BY  Orders.OrderID
         , Customers.ContactName
         , Orders.OrderDate
 )
SELECT   A.OrderID
         , A.ContactName
         , A.OrderDate
         , A.grand_total
         , (SELECT SUM(grand_total)
            FROM CTE B
            WHERE B.grand_total > A.grand_total) RunningTotal
FROM CTE A
ORDER BY RunningTotal

结果集

╔═════════╦═════════════════════╦═════════════════════════╦═════════════╦══════════════╗
║ OrderID ║     ContactName     ║        OrderDate        ║ grand_total ║ RunningTotal ║
╠═════════╬═════════════════════╬═════════════════════════╬═════════════╬══════════════╣
║   10267 ║ Peter Franken       ║ 1996-07-29 00:00:00.000 ║ 4031.00     ║ NULL         ║
║   10252 ║ Pascale Cartrain    ║ 1996-07-09 00:00:00.000 ║ 3730.00     ║ 4031.00      ║
║   10255 ║ Michael Holz        ║ 1996-07-12 00:00:00.000 ║ 2490.50     ║ 7761.00      ║
║   10263 ║ Roland Mendel       ║ 1996-07-23 00:00:00.000 ║ 2464.80     ║ 10251.50     ║
║   10258 ║ Roland Mendel       ║ 1996-07-17 00:00:00.000 ║ 2018.60     ║ 12716.30     ║
║   10249 ║ Karin Josephs       ║ 1996-07-05 00:00:00.000 ║ 1863.40     ║ 14734.90     ║
║   10250 ║ Mario Pontes        ║ 1996-07-08 00:00:00.000 ║ 1813.00     ║ 16598.30     ║
║   10260 ║ Henriette Pfalzheim ║ 1996-07-19 00:00:00.000 ║ 1746.20     ║ 18411.30     ║
║   10253 ║ Mario Pontes        ║ 1996-07-10 00:00:00.000 ║ 1444.80     ║ 20157.50     ║
║   10265 ║ Frédérique Citeaux  ║ 1996-07-25 00:00:00.000 ║ 1176.00     ║ 21602.30     ║
║   10257 ║ Carlos Hernández    ║ 1996-07-16 00:00:00.000 ║ 1119.90     ║ 22778.30     ║
║   10268 ║ Manuel Pereira      ║ 1996-07-30 00:00:00.000 ║ 1101.20     ║ 23898.20     ║
║   10264 ║ Maria Larsson       ║ 1996-07-24 00:00:00.000 ║ 724.50      ║ 24999.40     ║
╚═════════╩═════════════════════╩═════════════════════════╩═════════════╩══════════════╝