Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Die Differenz zwischen den einzelnen Zeilenwerten – Summenfehler

Was Sie im Wesentlichen brauchen, ist, vorübergehend vorzugeben, dass c2.reading nach Erreichen von 1.000.000 nicht umgebrochen, und das nur, wenn c2.reading < c1.reading . Das heißt, an diesem Punkt müssten Sie c2.reading erhöhen um 1.000.000, subtrahieren Sie dann c1.reading . Und wenn c2.reading >= c1.reading , sollte die Abfrage die "normale" Differenz berechnen, also c1.reading subtrahieren aus dem ursprünglichen (nicht vergrößerten) c2.reading Wert.

Eine Möglichkeit, diese Logik zu erreichen, wäre, etwas so Einfaches zu tun:

SUM(
  CASE WHEN c2.reading < c1.reading THEN 1000000 ELSE 0 END
  + c2.reading
  - ISNULL(c1.reading, c2.reading)
) AS Count1

Es gibt jedoch auch einen anderen Ansatz.

Ihre Lesewerte und damit auch die Differenzen zwischen zwei beliebigen Werten können niemals 1.000.000 überschreiten. Daher können Sie modulo frei anwenden 1.000.000 zu einer positiven Differenz und das gibt Ihnen die gleiche Differenz zurück:

d mod 1,000,000 = d

Darüber hinaus wirkt sich das Hinzufügen von Vielfachen von 1.000.000 zu einer positiven Differenz nicht auf das Ergebnis von Modulo 1.000.000 aus, da gemäß der Verteilungsfähigkeit der Modulo-Operation

  (d + 1,000,000 * n) mod 1,000,000 =
= d mod 1,000,000 + (1,000,000 * n) mod 1,000,000

Der erste Summand, d mod 1,000,000 ergibt d , der zweite, (1,000,000 * n) mod 1,000,000 ergibt 0, d + 0 = d .

Auf der anderen Seite addieren Sie 1.000.000 zu einem Negativ Differenz würde uns eine korrekte positive Differenz geben.

Also, um es zusammenzufassen:

  • Das Hinzufügen von 1.000.000 zu einer negativen Differenz ergibt eine (korrekte) positive Differenz,

  • eine positive Differenz modulo 1.000.000 ergibt die gleiche positive Differenz, und

  • Das Hinzufügen von 1.000.000 zu einer positiven Differenz wirkt sich nicht auf das Ergebnis von Modulo 1.000.000 aus.

Unter Berücksichtigung all dessen können wir mit dem folgenden universellen Ausdruck enden, um einen einzelnen Unterschied zu berechnen:

(1000000 + c2.reading - ISNULL(c1.reading, c2.reading)) % 1000000

wobei % ist der Modulo-Operator in Transact- SQL .

Fügen Sie den Ausdruck in SUM ein um die entsprechenden aggregierten Werte zu erhalten:

SUM((c2.reading + 1000000 - ISNULL(c1.reading, c2.reading)) % 1000000) AS Count1