Ce dont vous avez essentiellement besoin, c'est de prétendre temporairement que c2.reading
n'a pas bouclé après avoir atteint 1 000 000, et cela uniquement lorsque c2.reading < c1.reading
. Autrement dit, à ce stade, vous devrez augmenter c2.reading
par 1 000 000, puis soustrayez c1.reading
. Et quand c2.reading >= c1.reading
, la requête doit calculer la différence "normale", c'est-à-dire soustraire c1.reading
à partir de l'original (non augmenté) c2.reading
valeur.
Une façon d'atteindre cette logique serait de faire quelque chose d'aussi simple que ceci :
SUM(
CASE WHEN c2.reading < c1.reading THEN 1000000 ELSE 0 END
+ c2.reading
- ISNULL(c1.reading, c2.reading)
) AS Count1
Cependant, il existe également une approche différente.
Vos valeurs de lecture et, par conséquent, les différences entre deux d'entre elles ne peuvent jamais dépasser 1 000 000. Par conséquent, vous pouvez librement appliquer modulo 1 000 000 à une différence positive et cela vous rendra la même différence :
d mod 1,000,000 = d
De plus, ajouter des multiples de 1 000 000 à une différence positive n'affectera pas le résultat du modulo 1 000 000 car, selon la distributivité de l'opération modulo,
(d + 1,000,000 * n) mod 1,000,000 =
= d mod 1,000,000 + (1,000,000 * n) mod 1,000,000
La première somme, d mod 1,000,000
résultats en d
, le second, (1,000,000 * n) mod 1,000,000
donne 0, d + 0 = d
.
D'un autre côté, ajouter 1 000 000 à un négatif différence nous donnerait une différence positive correcte.
Donc, pour résumer,
-
ajouter 1 000 000 à une différence négative nous donne une différence positive (correcte),
-
une différence positive modulo 1 000 000 donne la même différence positive, et
-
l'ajout de 1 000 000 à une différence positive n'affecte pas le résultat du modulo 1 000 000.
Compte tenu de tout cela, nous pouvons nous retrouver avec l'expression universelle suivante pour calculer une seule différence :
(1000000 + c2.reading - ISNULL(c1.reading, c2.reading)) % 1000000
où %
est l'opérateur modulo dans Transact- SQL
.
Mettez l'expression dans SUM
pour obtenir les valeurs agrégées correspondantes :
SUM((c2.reading + 1000000 - ISNULL(c1.reading, c2.reading)) % 1000000) AS Count1