Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

La differenza tra ogni valore di riga - Sum Error

Ciò di cui hai essenzialmente bisogno è fingere temporaneamente che c2.reading non è andato a capo dopo aver raggiunto 1.000.000, e solo quando c2.reading < c1.reading . Cioè, a quel punto dovresti aumentare c2.reading per 1.000.000, quindi sottrarre c1.reading . E quando c2.reading >= c1.reading , la query dovrebbe calcolare la differenza "normale", ovvero sottrarre c1.reading dall'originale (non aumentato) c2.reading valore.

Un modo per raggiungere questa logica sarebbe fare qualcosa di semplice come questo:

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

Tuttavia, c'è anche un approccio diverso.

I tuoi valori di lettura e, di conseguenza, anche le differenze tra due di essi, non possono mai superare 1.000.000. Pertanto, puoi applicare liberamente modulo 1.000.000 di differenza positiva e questo ti restituirà la stessa differenza:

d mod 1,000,000 = d

Inoltre, l'aggiunta di multipli di 1.000.000 a una differenza positiva non influirà sul risultato di modulo 1.000.000 perché, in base alla distributività dell'operazione modulo,

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

Il primo ammonimento, d mod 1,000,000 risulta in d , il secondo, (1,000,000 * n) mod 1,000,000 restituisce 0, d + 0 = d .

D'altra parte, aggiungendo 1.000.000 a un negativo differenza ci darebbe una corretta differenza positiva.

Quindi, per riassumere,

  • aggiungendo 1.000.000 a una differenza negativa si ottiene una differenza positiva (corretta),

  • una differenza positiva modulo 1.000.000 produce la stessa differenza positiva e

  • l'aggiunta di 1.000.000 a una differenza positiva non influisce sul risultato del modulo 1.000.000.

Tenendo conto di tutto ciò, possiamo ottenere la seguente espressione universale per calcolare una singola differenza:

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

dove % è l'operatore modulo in Transact- SQL .

Inserisci l'espressione in SUM per ottenere i valori aggregati corrispondenti:

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