累计到前一行

Ste*_*eve 15 sql-server sql-server-2012 window-functions

我需要一些窗口函数方面的帮助。我知道你可以计算一个窗口内的总和和一个窗口内的运行总数。但是是否可以计算先前的运行总计,即不包括当前行的运行总计?

我假设您需要使用ROWorRANGE参数。我知道有一个CURRENT ROW选项,但我需要CURRENT ROW - 1,这是无效的语法。我对这些ROWRANGE论点的了解有限,因此将不胜感激地收到任何帮助。

我知道这个问题有很多解决方案,但我希望了解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 BYOVER子句中存在an 时的默认范围- 否则,没有ORDER BY默认值是整个分区。