Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

A diferença entre cada valor de linha - Erro de soma


O que você precisa essencialmente é fingir temporariamente que c2.reading não terminou depois de atingir 1.000.000, e isso somente quando c2.reading < c1.reading . Ou seja, nesse ponto você precisaria aumentar c2.reading por 1.000.000, então subtraia c1.reading . E quando c2.reading >= c1.reading , a consulta deve calcular a diferença "normal", ou seja, subtrair c1.reading do original (não aumentado) c2.reading valor.

Uma maneira de alcançar essa lógica seria fazer algo tão simples quanto isso:
SUM(
  CASE WHEN c2.reading < c1.reading THEN 1000000 ELSE 0 END
  + c2.reading
  - ISNULL(c1.reading, c2.reading)
) AS Count1

No entanto, há também uma abordagem diferente.

Seus valores de leitura e, como consequência, as diferenças entre quaisquer dois deles, nunca podem exceder 1.000.000. Portanto, você pode aplicar livremente modulo 1.000.000 para uma diferença positiva e isso lhe dará a mesma diferença de volta:
d mod 1,000,000 = d

Além disso, adicionar múltiplos de 1.000.000 a uma diferença positiva não afetará o resultado do módulo 1.000.000 porque, de acordo com a distributividade da operação do módulo,
  (d + 1,000,000 * n) mod 1,000,000 =
= d mod 1,000,000 + (1,000,000 * n) mod 1,000,000

A primeira soma, d mod 1,000,000 resulta em d , o segundo, (1,000,000 * n) mod 1,000,000 produz 0, d + 0 = d .

Por outro lado, adicionar 1.000.000 a um valor negativo diferença nos daria uma diferença positiva correta.

Entao, para resumir,

  • adicionar 1.000.000 a uma diferença negativa nos dá uma diferença positiva (correta),

  • uma diferença positiva módulo 1.000.000 produz a mesma diferença positiva, e

  • adicionar 1.000.000 a uma diferença positiva não afeta o resultado do módulo 1.000.000.

Levando tudo isso em consideração, podemos terminar com a seguinte expressão universal para calcular uma única diferença:
(1000000 + c2.reading - ISNULL(c1.reading, c2.reading)) % 1000000

onde % é o operador de módulo em Transact- SQL .

Coloque a expressão em SUM para obter os valores agregados correspondentes:
SUM((c2.reading + 1000000 - ISNULL(c1.reading, c2.reading)) % 1000000) AS Count1