[英]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个表(寻找
Orders
和OrderDetails
)这是我到目前为止所。
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.