Laufende Summe zur vorherigen Zeile

14

Ich brauche Hilfe bei den Fensterfunktionen. Ich weiß, dass Sie die Summe innerhalb eines Fensters und die laufende Summe innerhalb eines Fensters berechnen können. Aber ist es möglich, die vorherige laufende Summe zu berechnen, dh die laufende Summe ohne die aktuelle Zeile?

Ich nehme an, Sie müssten das Argument ROWoder verwenden RANGE. Ich weiß, es gibt eine CURRENT ROWOption, aber ich würde brauchen CURRENT ROW - 1, die ungültige Syntax ist. Mein Wissen über die ROWund RANGEArgumente ist begrenzt, so dass jede Hilfe dankbar aufgenommen werden würde.

Ich weiß, dass es viele Lösungen für dieses Problem gibt, aber ich möchte die Argumente verstehen ROW, RANGEund ich gehe davon aus, dass das Problem damit geknackt werden kann. Ich habe eine Möglichkeit zur Berechnung der vorherigen laufenden Summe angegeben, aber ich frage mich, ob es eine bessere Möglichkeit gibt:

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
Steve
quelle

Antworten:

22

Die Antwort ist zu verwenden 1 PRECEDING, nicht CURRENT ROW -1. Verwenden Sie in Ihrer Abfrage also:

    , SUM(s.OrderQty) OVER (PARTITION BY  SalesOrderID 
                            ORDER BY SalesOrderDetailID
                            ROWS BETWEEN UNBOUNDED PRECEDING 
                                     AND 1 PRECEDING) 
    AS  PreviousRunningTotal

Beachten Sie auch, dass bei Ihrer anderen Berechnung:

    , SUM(s.OrderQty) OVER (PARTITION BY  SalesOrderID
                            ORDER BY SalesOrderDetailID) ...

SQL-Server verwendet die Standardeinstellung * RANGE UNBOUNDED PRECEDING AND CURRENT ROW . Ich denke, dass es einen Effizienzunterschied gibt und ROWS UNBOUNDED PRECEDING AND CURRENT ROWder vorzuziehen ist (nach dem Testen natürlich und wenn es die gewünschten Ergebnisse gibt).

Weitere Informationen finden Sie im Blog-Artikel von @Aaron Bertrand , einschließlich Leistungstests: Beste Ansätze für die Ausführung von Gesamtwerten - aktualisiert für SQL Server 2012

* Dies ist natürlich der Standardbereich, wenn eine ORDER BYin der OVERKlausel enthalten ist - andernfalls ist ohne ORDER BYdie Standardeinstellung die gesamte Partition.

ypercubeᵀᴹ
quelle