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

Forskellen mellem hver rækkeværdi - Sumfejl

Det, du i bund og grund har brug for, er midlertidigt at foregive, at c2.reading gik ikke rundt efter at have nået 1.000.000, og det kun når c2.reading < c1.reading . Det vil sige, på det tidspunkt skulle du øge c2.reading med 1.000.000, og træk derefter c1.reading fra . Og når c2.reading >= c1.reading , skal forespørgslen beregne den "normale" forskel, dvs. trække c1.reading fra fra den originale (ikke-forøgede) c2.reading værdi.

En måde at opnå den logik på ville være at gøre noget så ligetil som dette:

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

Men der er også en anden tilgang.

Dine læseværdier, og som følge heraf også forskelle mellem to af dem, kan aldrig overstige 1.000.000. Derfor kan du frit anvende modulo 1.000.000 til en positiv forskel, og det vil give dig den samme forskel tilbage:

d mod 1,000,000 = d

Desuden vil tilføjelse af multipla af 1.000.000 til en positiv forskel ikke påvirke resultatet af modulo 1.000.000, fordi, i henhold til fordelingsevnen af ​​modulo-operationen,

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

Den første summand, d mod 1,000,000 resulterer i d , den anden, (1,000,000 * n) mod 1,000,000 giver 0, d + 0 = d .

På den anden side tilføjer du 1.000.000 til en negativ forskel ville give os en korrekt positiv forskel.

Så for at opsummere,

  • at lægge 1.000.000 til en negativ forskel giver os en (korrekt) positiv forskel,

  • en positiv forskel modulo 1.000.000 giver den samme positive forskel, og

  • tilføjelse af 1.000.000 til en positiv forskel påvirker ikke resultatet af modulo 1.000.000.

Tager vi alt det i betragtning, kan vi ende med følgende universelle udtryk for at beregne en enkelt forskel:

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

hvor % er modulo-operatøren i Transact- SQL .

Indsæt udtrykket i SUM for at få de tilsvarende aggregerede værdier:

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



  1. Oracle opdelt bord

  2. Sådan bruges JDBC til at forbinde MySql-databasen

  3. Oracle sql-forespørgsel for at gruppere fortløbende poster efter dato

  4. Hvordan beregner man DATO-forskel i PostgreSQL?