sql >> Base de Datos >  >> RDS >> Sqlserver

La diferencia entre cada valor de fila - Error de suma

Lo que esencialmente necesitas es pretender temporalmente que c2.reading no terminó después de llegar a 1,000,000, y eso solo cuando c2.reading < c1.reading . Es decir, en ese momento necesitarías aumentar c2.reading por 1,000,000, luego reste c1.reading . Y cuando c2.reading >= c1.reading , la consulta debe calcular la diferencia "normal", es decir, restar c1.reading del original (no aumentado) c2.reading valor.

Una forma de lograr esa lógica sería hacer algo tan sencillo como esto:

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

Sin embargo, también hay un enfoque diferente.

Sus valores de lectura y, como consecuencia, las diferencias entre dos de ellos, nunca pueden exceder 1,000,000. Por lo tanto, puede aplicar libremente modulo 1,000,000 a una diferencia positiva y eso le devolverá la misma diferencia:

d mod 1,000,000 = d

Además, sumar múltiplos de 1.000.000 a una diferencia positiva no afectará el resultado del módulo 1.000.000 porque, según la distributividad de la operación módulo,

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

El primer sumando, d mod 1,000,000 da como resultado d , el segundo, (1,000,000 * n) mod 1,000,000 da como resultado 0, d + 0 = d .

Por otro lado, sumar 1,000,000 a un negativo diferencia nos daría una diferencia positiva correcta.

Entonces, para resumir,

  • sumando 1,000,000 a una diferencia negativa nos da una diferencia positiva (correcta),

  • una diferencia positiva módulo 1,000,000 produce la misma diferencia positiva, y

  • agregar 1,000,000 a una diferencia positiva no afecta el resultado del módulo 1,000,000.

Teniendo todo eso en cuenta, podemos terminar con la siguiente expresión universal para calcular una sola diferencia:

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

donde % es el operador de módulo en Transact- SQL .

Pon la expresión en SUM para obtener los valores agregados correspondientes:

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