J'ai un ensemble de données composé de valeurs horodatées et de valeurs absolues (mètres). Parfois, les valeurs du compteur sont réinitialisées à zéro, ce qui signifie que je dois parcourir et calculer un delta un par un, puis l'additionner pour obtenir le total pour une période donnée.Méthode efficace pour calculer la somme des deltas entre des rangées consécutives?
Par exemple:
Timestamp Value
2009-01-01 100
2009-01-02 105
2009-01-03 120
2009-01-04 0
2009-01-05 9
le total ici est 29, calculé comme suit:
(105 - 100) + (120 - 105) + (0) + (9 - 0) = 29
J'utilise un serveur MS-SQL pour cela, et ouvert à toutes les suggestions.
En ce moment, je suis en utilisant un curseur pour ce faire, qui vérifie que le delta est pas négatif, et totalise en place:
DECLARE CURSOR curTest CURSOR FAST_FORWARD FOR
SELECT value FROM table ORDER BY timestamp
OPEN curTest
DECLARE @delta bigint, @current bigint, @last bigint
SET @delta = 0
FETCH curTest INTO @current
WHILE @@FETCH_STATUS = 0
BEGIN
IF (@current IS NOT NULL) AND (@current > 0)
BEGIN
IF (@last IS NOT NULL) AND (@current > @last)
SET @delta = @delta + (@current - @last)
SET @last = @current
FETCH curTest INTO @current
END
END
CLOSE curTest
DEALLOCATE curTest
Ce serait bien d'obtenir un ensemble de données comme :
Timestamp Value LastValue
2009-01-01 100 NULL
2009-01-02 105 100
2009-01-03 120 105
2009-01-04 0 120
2009-01-05 9 0
comme il serait alors facile de saisir les deltas, filtre pour (valeur> LastValue) et faire une SOMME().
J'ai essayé:
SELECT m1.timestamp, m1.value,
(SELECT TOP 1 m2.value FROM table WHERE m2.timestamp < m1.timestamp ORDER BY m2.timestamp DESC) as LastValue
FROM table
, mais cela se fait avéré être plus lent que le curseur: Quand je lance ces ensemble en studio SQL avec « plan d'exécution du spectacle » sur, le coût relatif de ce 100% (avec 7 ou 8 opérations - la majorité dans un index indexé en cluster sur horodatage), et le curseur est 0% (avec 3 opérations).
(Ce que je ne montre pas ici pour simplifier, c'est que j'ai plusieurs ensembles de nombres différents, avec une clé étrangère dans ce tableau aussi - il y a donc toujours une clause WHERE qui limite à un ensemble spécifique. plusieurs endroits où je calcule ces totaux pour une période de temps donnée pour plusieurs ensembles à la fois, et ainsi il devient tout à fait le goulot d'étranglement des performances.La méthode sans curseur peut également être facilement modifiée à GROUP BY la clé et retourner tous les ensembles mais cela est en fait encore plus lent dans mes tests que de courir le curseur plusieurs fois, car il y a le surcroît de travail des opérations GROUP BY et SUM(), en plus de ralentir globalement.)
+1 pour l'utilisation de row_number() –