Điều bạn cần về cơ bản là tạm thời giả vờ rằng c2.reading
không kết thúc sau khi đạt 1.000.000 và chỉ khi c2.reading < c1.reading
. Tức là tại thời điểm đó, bạn cần tăng c2.reading
1.000.000, sau đó trừ đi c1.reading
. Và khi c2.reading >= c1.reading
, truy vấn sẽ tính toán sự khác biệt "bình thường", tức là trừ đi c1.reading
từ bản gốc (không tăng) c2.reading
giá trị.
Một cách để đạt được logic đó là làm điều gì đó đơn giản như sau:
SUM(
CASE WHEN c2.reading < c1.reading THEN 1000000 ELSE 0 END
+ c2.reading
- ISNULL(c1.reading, c2.reading)
) AS Count1
Tuy nhiên, cũng có một cách tiếp cận khác.
Giá trị đọc của bạn, và do đó, sự khác biệt giữa hai giá trị bất kỳ, không bao giờ có thể vượt quá 1.000.000. Do đó, bạn có thể thoải mái áp dụng modulo 1.000.000 đến một sự khác biệt tích cực và điều đó sẽ mang lại cho bạn sự khác biệt tương tự:
d mod 1,000,000 = d
Hơn nữa, việc thêm bội số của 1.000.000 vào một hiệu số dương sẽ không ảnh hưởng đến kết quả của modulo 1.000.000 bởi vì, theo phân phối của hoạt động modulo,
(d + 1,000,000 * n) mod 1,000,000 =
= d mod 1,000,000 + (1,000,000 * n) mod 1,000,000
Triệu hồi đầu tiên và d mod 1,000,000
kết quả là d
, cái thứ hai, (1,000,000 * n) mod 1,000,000
cho ra 0, d + 0 = d
.
Mặt khác, thêm 1.000.000 vào âm sự khác biệt sẽ cung cấp cho chúng tôi một sự khác biệt tích cực chính xác.
Vì vậy, tóm lại,
-
thêm 1.000.000 vào một chênh lệch âm sẽ cho chúng tôi một chênh lệch dương (đúng),
-
một mô-đun khác biệt dương 1.000.000 mang lại cùng một sự khác biệt dương và
-
Việc thêm 1.000.000 vào một chênh lệch dương không ảnh hưởng đến kết quả của modulo 1.000.000.
Tính đến tất cả những điều đó, chúng ta có thể kết thúc bằng biểu thức phổ quát sau để tính một sự khác biệt duy nhất:
(1000000 + c2.reading - ISNULL(c1.reading, c2.reading)) % 1000000
ở đâu %
là toán tử modulo trong Giao dịch- SQL
.
Đặt biểu thức vào SUM
để nhận các giá trị tổng hợp tương ứng:
SUM((c2.reading + 1000000 - ISNULL(c1.reading, c2.reading)) % 1000000) AS Count1