基本的に必要なのは、一時的に c2.reading
のふりをすることです c2.reading < c1.reading
の場合のみ、1,000,000 に達した後はラップアラウンドしません .つまり、その時点で c2.reading
を増やす必要があります 1,000,000 ずつ、c1.reading
を減算します。 . c2.reading >= c1.reading
の場合 、クエリは「通常の」差を計算する必要があります。つまり、 c1.reading
を減算します 元の (増加していない) c2.reading
から
そのロジックを実現する 1 つの方法は、次のように単純なことを行うことです。
SUM(
CASE WHEN c2.reading < c1.reading THEN 1000000 ELSE 0 END
+ c2.reading
- ISNULL(c1.reading, c2.reading)
) AS Count1
ただし、別のアプローチもあります。
読み取り値、およびその結果として、それらの 2 つの値の差も 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
になります 、2番目のもの、 (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