Това, от което се нуждаете, е временно да се преструвате, че c2.reading не се уви след достигане на 1 000 000 и това само когато c2.reading < c1.reading . Тоест в този момент ще трябва да увеличите c2.reading с 1 000 000, след което извадете c1.reading . И когато c2.reading >= c1.reading , заявката трябва да изчисли "нормалната" разлика, т.е. да извади c1.reading от оригиналния (неувеличен) c2.reading стойност.
Един от начините да постигнете тази логика е да направите нещо толкова просто като това:
SUM(
CASE WHEN c2.reading < c1.reading THEN 1000000 ELSE 0 END
+ c2.reading
- ISNULL(c1.reading, c2.reading)
) AS Count1
Съществува обаче и различен подход.
Вашите стойности на четене и, като следствие, разликите между всеки две от тях, никога не могат да надхвърлят 1 000 000. Следователно можете свободно да прилагате modulo 1 000 000 към положителна разлика и това ще ви върне същата разлика:
d mod 1,000,000 = d
Освен това добавянето на кратни на 1 000 000 към положителна разлика няма да повлияе на резултата от модул 1 000 000, тъй като според разпределимостта на операцията модул,
(d + 1,000,000 * n) mod 1,000,000 =
= d mod 1,000,000 + (1,000,000 * n) mod 1,000,000
Първото събираемо, d mod 1,000,000 води до d , вторият, (1,000,000 * n) mod 1,000,000 дава 0, d + 0 = d .
От друга страна, добавяне на 1 000 000 към отрицателно разлика ще ни даде правилна положителна разлика.
И така, за да обобщим,
-
добавянето на 1 000 000 към отрицателна разлика ни дава (правилна) положителна разлика,
-
положителна разлика по модул 1 000 000 дава същата положителна разлика и
-
добавянето на 1 000 000 към положителна разлика не влияе на резултата от модул 1 000 000.
Като вземем всичко това предвид, можем да завършим със следния универсален израз за изчисляване на една разлика:
(1000000 + c2.reading - ISNULL(c1.reading, c2.reading)) % 1000000
където % е модулният оператор в Transact- SQL
.
Поставете израза в SUM за да получите съответните обобщени стойности:
SUM((c2.reading + 1000000 - ISNULL(c1.reading, c2.reading)) % 1000000) AS Count1