Total cumulé à la ligne précédente


14

J'ai besoin d'aide pour les fonctions de fenêtrage. Je sais que vous pouvez calculer la somme dans une fenêtre et le total cumulé dans une fenêtre. Mais est-il possible de calculer le total cumulé précédent, c'est-à-dire le total cumulé hors ligne actuelle?

Je suppose que vous auriez besoin d'utiliser l' argument ROWor RANGE. Je sais qu'il y a une CURRENT ROWoption mais j'aurais besoin d' CURRENT ROW - 1une syntaxe invalide. Ma connaissance des arguments ROWet RANGEest limitée, donc toute aide serait reçue avec gratitude.

Je sais qu'il ya beaucoup de solutions à ce problème, mais je cherche à comprendre les ROW, RANGEarguments et je suppose que le problème peut être craqué avec ces derniers . J'ai inclus une façon possible de calculer le total cumulé précédent mais je me demande s'il y a une meilleure façon:

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

Réponses:


22

La réponse est d'utiliser 1 PRECEDING, non CURRENT ROW -1. Donc, dans votre requête, utilisez:

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

Notez également que sur votre autre calcul:

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

SQL-Server utilise la valeur par défaut * RANGE UNBOUNDED PRECEDING AND CURRENT ROW . Je pense qu'il y a une différence d'efficacité et ROWS UNBOUNDED PRECEDING AND CURRENT ROWest à privilégier (après test bien sûr et si ça donne les résultats que l'on veut).

Beaucoup plus de détails que vous pouvez trouver dans l'article de blog de @Aaron Bertrand , y compris les tests de performances: Meilleures approches pour l'exécution des totaux - mis à jour pour SQL Server 2012

* il s'agit bien sûr de la plage par défaut lorsqu'un an ORDER BYest présent dans la OVERclause - sinon, sans ORDER BYla valeur par défaut, c'est la partition entière.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.