Det, du i bund og grund har brug for, er midlertidigt at foregive, at c2.reading
gik ikke rundt efter at have nået 1.000.000, og det kun når c2.reading < c1.reading
. Det vil sige, på det tidspunkt skulle du øge c2.reading
med 1.000.000, og træk derefter c1.reading
fra . Og når c2.reading >= c1.reading
, skal forespørgslen beregne den "normale" forskel, dvs. trække c1.reading
fra fra den originale (ikke-forøgede) c2.reading
værdi.
En måde at opnå den logik på ville være at gøre noget så ligetil som dette:
SUM(
CASE WHEN c2.reading < c1.reading THEN 1000000 ELSE 0 END
+ c2.reading
- ISNULL(c1.reading, c2.reading)
) AS Count1
Men der er også en anden tilgang.
Dine læseværdier, og som følge heraf også forskelle mellem to af dem, kan aldrig overstige 1.000.000. Derfor kan du frit anvende modulo 1.000.000 til en positiv forskel, og det vil give dig den samme forskel tilbage:
d mod 1,000,000 = d
Desuden vil tilføjelse af multipla af 1.000.000 til en positiv forskel ikke påvirke resultatet af modulo 1.000.000, fordi, i henhold til fordelingsevnen af modulo-operationen,
(d + 1,000,000 * n) mod 1,000,000 =
= d mod 1,000,000 + (1,000,000 * n) mod 1,000,000
Den første summand, d mod 1,000,000
resulterer i d
, den anden, (1,000,000 * n) mod 1,000,000
giver 0, d + 0 = d
.
På den anden side tilføjer du 1.000.000 til en negativ forskel ville give os en korrekt positiv forskel.
Så for at opsummere,
-
at lægge 1.000.000 til en negativ forskel giver os en (korrekt) positiv forskel,
-
en positiv forskel modulo 1.000.000 giver den samme positive forskel, og
-
tilføjelse af 1.000.000 til en positiv forskel påvirker ikke resultatet af modulo 1.000.000.
Tager vi alt det i betragtning, kan vi ende med følgende universelle udtryk for at beregne en enkelt forskel:
(1000000 + c2.reading - ISNULL(c1.reading, c2.reading)) % 1000000
hvor %
er modulo-operatøren i Transact- SQL
.
Indsæt udtrykket i SUM
for at få de tilsvarende aggregerede værdier:
SUM((c2.reading + 1000000 - ISNULL(c1.reading, c2.reading)) % 1000000) AS Count1