sql >> Database >  >> RDS >> Sqlserver

Het verschil tussen elke rijwaarde - Somfout

Wat je in wezen nodig hebt, is om tijdelijk te doen alsof c2.reading niet rondliep na het bereiken van 1.000.000, en dat alleen wanneer c2.reading < c1.reading . Dat wil zeggen, op dat moment zou u c2.reading . moeten verhogen met 1.000.000, trek dan c1.reading af . En wanneer c2.reading >= c1.reading , moet de query het "normale" verschil berekenen, d.w.z. c1.reading aftrekken van de originele (niet-verhoogde) c2.reading waarde.

Een manier om die logica te bereiken zou zijn om zoiets eenvoudigs als dit te doen:

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

Er is echter ook een andere benadering.

Uw leeswaarden, en als gevolg daarvan ook de verschillen tussen deze twee, kunnen nooit meer dan 1.000.000 bedragen. Daarom kunt u vrij modulo toepassen 1.000.000 tot een positief verschil en dat geeft je hetzelfde verschil terug:

d mod 1,000,000 = d

Bovendien heeft het optellen van veelvouden van 1.000.000 bij een positief verschil geen invloed op het resultaat van modulo 1.000.000 omdat, volgens de distributiviteit van de modulo-bewerking,

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

De eerste som, d mod 1,000,000 resulteert in d , de tweede, (1,000,000 * n) mod 1,000,000 levert 0 op, d + 0 = d .

Aan de andere kant, het toevoegen van 1.000.000 aan een negatief verschil zou ons een correct positief verschil opleveren.

Kortom,

  • 1.000.000 optellen bij een negatief verschil geeft ons een (correct) positief verschil,

  • een positief verschil modulo 1.000.000 levert hetzelfde positieve verschil op, en

  • 1.000.000 optellen bij een positief verschil heeft geen invloed op het resultaat van modulo 1.000.000.

Als we dat allemaal in aanmerking nemen, kunnen we de volgende universele uitdrukking krijgen om een ​​enkel verschil te berekenen:

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

waar % is de modulo-operator in Transact- SQL .

Zet de uitdrukking in SUM om de corresponderende geaggregeerde waarden te krijgen:

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



  1. MySQL:time-out voor vergrendelingswachttijd overschreden

  2. SQL Server 2017:Beschikbare functies op Linux

  3. SQL enkele kolom verdeeld over meerdere kolommen

  4. Oracle SQL groeperen op kolom met aantal, maar alleen als de kolom null of 0 . is