Ste*_*eve 15 sql-server sql-server-2012 window-functions
我需要一些窗口函数方面的帮助。我知道你可以计算一个窗口内的总和和一个窗口内的运行总数。但是是否可以计算先前的运行总计,即不包括当前行的运行总计?
我假设您需要使用ROW
orRANGE
参数。我知道有一个CURRENT ROW
选项,但我需要CURRENT ROW - 1
,这是无效的语法。我对这些ROW
和RANGE
论点的了解有限,因此将不胜感激地收到任何帮助。
我知道这个问题有很多解决方案,但我希望了解ROW
,RANGE
参数,并且我认为可以用这些来解决问题。我已经包含了一种可能的方法来计算以前的运行总数,但我想知道是否有更好的方法:
USE AdventureWorks2012
SELECT s.SalesOrderID
, s.SalesOrderDetailID
, s.OrderQty
, SUM(s.OrderQty) OVER (PARTITION BY SalesOrderID) AS RunningTotal
, SUM(s.OrderQty) OVER (PARTITION BY SalesOrderID
ORDER BY SalesOrderDetailID) - s.OrderQty AS PreviousRunningTotal
-- Sudo code - I know this does not work
--, SUM(s.OrderQty) OVER (PARTITION BY SalesOrderID
-- ORDER BY SalesOrderDetailID
-- ROWS BETWEEN UNBOUNDED PRECEDING
-- AND CURRENT ROW - 1)
-- AS SudoCodePreviousRunningTotal
FROM Sales.SalesOrderDetail s
WHERE SalesOrderID IN (43670, 43669, 43667, 43663)
ORDER BY s.SalesOrderID
, s.SalesOrderDetailID
, s.OrderQty
Run Code Online (Sandbox Code Playgroud)
ype*_*eᵀᴹ 23
答案是使用1 PRECEDING
,而不是CURRENT ROW -1
。因此,在您的查询中,请使用:
, SUM(s.OrderQty) OVER (PARTITION BY SalesOrderID
ORDER BY SalesOrderDetailID
ROWS BETWEEN UNBOUNDED PRECEDING
AND 1 PRECEDING)
AS PreviousRunningTotal
Run Code Online (Sandbox Code Playgroud)
另请注意,在您的其他计算中:
, SUM(s.OrderQty) OVER (PARTITION BY SalesOrderID
ORDER BY SalesOrderDetailID) ...
Run Code Online (Sandbox Code Playgroud)
SQL-Server 使用默认的* RANGE UNBOUNDED PRECEDING AND CURRENT ROW
。我认为存在效率差异并且ROWS UNBOUNDED PRECEDING AND CURRENT ROW
是首选(当然在测试之后并且如果它给出你想要的结果)。
您可以在@Aaron Bertrand的博客文章中找到更多详细信息,包括性能测试:运行总计的最佳方法 - 针对 SQL Server 2012 更新
* 这当然ORDER BY
是OVER
子句中存在an 时的默认范围- 否则,没有ORDER BY
默认值是整个分区。