Wat je in wezen nodig hebt, is om tijdelijk te doen alsof c2.reading
niet rondliep na het bereiken van 1.000.000, en dat alleen wanneer c2.reading < c1.reading
. Dat wil zeggen, op dat moment zou u c2.reading
. moeten verhogen met 1.000.000, trek dan c1.reading
af . En wanneer c2.reading >= c1.reading
, moet de query het "normale" verschil berekenen, d.w.z. c1.reading
aftrekken van de originele (niet-verhoogde) c2.reading
waarde.
Een manier om die logica te bereiken zou zijn om zoiets eenvoudigs als dit te doen:
SUM(
CASE WHEN c2.reading < c1.reading THEN 1000000 ELSE 0 END
+ c2.reading
- ISNULL(c1.reading, c2.reading)
) AS Count1
Er is echter ook een andere benadering.
Uw leeswaarden, en als gevolg daarvan ook de verschillen tussen deze twee, kunnen nooit meer dan 1.000.000 bedragen. Daarom kunt u vrij modulo toepassen 1.000.000 tot een positief verschil en dat geeft je hetzelfde verschil terug:
d mod 1,000,000 = d
Bovendien heeft het optellen van veelvouden van 1.000.000 bij een positief verschil geen invloed op het resultaat van modulo 1.000.000 omdat, volgens de distributiviteit van de modulo-bewerking,
(d + 1,000,000 * n) mod 1,000,000 =
= d mod 1,000,000 + (1,000,000 * n) mod 1,000,000
De eerste som, d mod 1,000,000
resulteert in d
, de tweede, (1,000,000 * n) mod 1,000,000
levert 0 op, d + 0 = d
.
Aan de andere kant, het toevoegen van 1.000.000 aan een negatief verschil zou ons een correct positief verschil opleveren.
Kortom,
-
1.000.000 optellen bij een negatief verschil geeft ons een (correct) positief verschil,
-
een positief verschil modulo 1.000.000 levert hetzelfde positieve verschil op, en
-
1.000.000 optellen bij een positief verschil heeft geen invloed op het resultaat van modulo 1.000.000.
Als we dat allemaal in aanmerking nemen, kunnen we de volgende universele uitdrukking krijgen om een enkel verschil te berekenen:
(1000000 + c2.reading - ISNULL(c1.reading, c2.reading)) % 1000000
waar %
is de modulo-operator in Transact- SQL
.
Zet de uitdrukking in SUM
om de corresponderende geaggregeerde waarden te krijgen:
SUM((c2.reading + 1000000 - ISNULL(c1.reading, c2.reading)) % 1000000) AS Count1