sql >> Databasteknik >  >> RDS >> Sqlserver

Skillnaden mellan varje radvärde - Sum Error

Vad du egentligen behöver är att tillfälligt låtsas att c2.reading gick inte runt efter att ha nått 1 000 000, och det bara när c2.reading < c1.reading . Det vill säga, vid den tidpunkten skulle du behöva öka c2.reading med 1 000 000, subtrahera sedan c1.reading . Och när c2.reading >= c1.reading , bör frågan beräkna den "normala" skillnaden, dvs subtrahera c1.reading från den ursprungliga (icke-ökade) c2.reading värde.

Ett sätt att uppnå den logiken skulle vara att göra något så enkelt som detta:

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

Men det finns också ett annat tillvägagångssätt.

Dina avläsningsvärden, och, som en konsekvens, även skillnader mellan två av dem, kan aldrig överstiga 1 000 000. Därför kan du fritt använda modulo 1 000 000 till en positiv skillnad och det ger dig samma skillnad tillbaka:

d mod 1,000,000 = d

Att lägga till multiplar av 1 000 000 till en positiv skillnad kommer dessutom inte att påverka resultatet av modulo 1 000 000 eftersom, enligt modulo-operationens fördelningsförmåga,

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

Den första summan, d mod 1,000,000 resulterar i d , den andra, (1,000,000 * n) mod 1,000,000 ger 0, d + 0 = d .

Å andra sidan, lägga till 1 000 000 till ett negativt skillnad skulle ge oss en korrekt positiv skillnad.

Så, för att sammanfatta,

  • lägga till 1 000 000 till en negativ skillnad ger oss en (korrekt) positiv skillnad,

  • en positiv skillnad modulo 1 000 000 ger samma positiva skillnad, och

  • att lägga till 1 000 000 till en positiv skillnad påverkar inte resultatet av modulo 1 000 000.

Med hänsyn till allt detta kan vi sluta med följande universella uttryck för att beräkna en enda skillnad:

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

där % är modulo-operatören i Transact- SQL .

Lägg uttrycket i SUM för att få motsvarande aggregerade värden:

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



  1. Jämföra Galera Cluster Cloud-erbjudanden:Del ett Amazon AWS

  2. Kan inte installera mysql2 gem

  3. LEFT OUTER JOIN på arraykolumn med flera värden

  4. Hur väljer man det klustrade indexet i SQL Server?