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 devez utiliser l'argument ROW
ou RANGE
. Je sais qu'il y a un CURRENT ROW
option mais j'aurais besoin de CURRENT ROW - 1
, qui n'est pas une syntaxe valide. Ma connaissance des arguments ROW
et RANGE
étant limitée, toute aide serait reçue avec gratitude.
Je sais qu'il existe de nombreuses solutions à ce problème, mais je cherche à comprendre les arguments ROW
, RANGE
et je suppose que le problème peut être résolu 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
La réponse est d'utiliser 1 PRECEDING
, ne pas 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 ROW
est à privilégier (après test bien sûr et s'il donne les résultats souhaités).
Beaucoup plus de détails que vous pouvez trouver dans l'article de blog par @ Aaron Bertrand , y compris les tests de performances: Meilleures approches pour l'exécution des totaux - mis à jour pour SQL Server 2012
* c'est bien sûr la plage par défaut quand un ORDER BY
est présent dans la clause OVER
- sinon, sans ORDER BY
la valeur par défaut est toute la partition.