简体   繁体   English

SQL Subtotal和Grand Totals

[英]SQL Subtotal and Grand Totals

Will my code work for solving the following problem? 我的代码是否可以解决以下问题? The total cost of all items ordered for all orders placed in July, 1996. Looking at 2 tables ( Orders and OrderDetails ) this is what I have so far. 下令摆在七月的所有订单的所有项目的总成本,在1996年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;

The intent is to find the sum of each row and keep that number then sum the rows to produce a grand total. 目的是找到每一行的总和并保留该数字,然后对行进行求和以产生总计。 When I run the query it definitely doesn't produce what should be. 当我运行查询时,它肯定不会产生应该是什么。

Try this: 尝试这个:

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), ...) will group the source rows by o.OrderID, c.ContactName, o.OrderDate and, also, will compute the SUM for every OrderID, ContactName, OrderDate pair of values. GROUPING SETS ((o.OrderID, c.ContactName, o.OrderDate), ...)将按o.OrderID, c.ContactName, o.OrderDate对源行进行o.OrderID, c.ContactName, o.OrderDate并且还将为每个OrderID, ContactName, OrderDate计算SUM OrderID, ContactName, OrderDate值对。

GROUPING SETS ((...), ()) instructs SQL Server to compute, also, the grand total (total of all order totals): 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), ());

Results: 结果:

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 (..., ())

There are many ways to do this. 有很多方法可以做到这一点。

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

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

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

Do not use Shiva's solution since COMPUTE is defunct in SQL Server 2012! 不要使用Shiva的解决方案,因为COMPUTE在SQL Server 2012中已经不存在了!

Here are some issues that I corrected in my solution. 以下是我在解决方案中纠正的一些问题。

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

Since you were not specific, I chose a simple sum by each customers order id with a total month to-date for the customer regardless of the order id. 由于您不是特定的,我选择了每个客户订单ID的简单总和,其中包括客户的总月份,无论订单ID如何。

To solve this, I used a OVER clause. 为了解决这个问题,我使用了OVER子句。 Since I did not have test data or tables from you, It is your homework to check the solution for syntax errors. 由于我没有您的测试数据或表格,因此检查解决方案是否存在语法错误是您的功课。

-- 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 
;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

Result Set 结果集

╔═════════╦═════════════════════╦═════════════════════════╦═════════════╦══════════════╗
║ 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     ║
╚═════════╩═════════════════════╩═════════════════════════╩═════════════╩══════════════╝

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM