Tillvägagångssätt
Du har två fel i ditt tillvägagångssätt, vilket introducerar komplexitet.
-
Alla kolumner som kan härledas, till exempel din AVERAGE bör inte lagras.
Om den lagras utgör den en dubblettkolumn ... vilket leder till en uppdateringsanomali, som du upplever. Poängen med normalisering är att eliminera dataduplicering och därmed eliminera uppdateringsavvikelser. Det eliminerar också komplex kod som denna, såväl som triggers, etc.
Beräkna SUM(), AVG(), etc, i resultatuppsättningen endast , i farten.
-
Användning av ID-kolumner, vilket i princip betyder att du har ett registerarkiveringssystem, ingen relationsdatabas. Utan att räkna upp de många problem som det orsakar (jag har gjort det någon annanstans), bara namnge problemet här
- du har ett ID-tänk.
ID:t är en fysisk postpekare, det ger inte radunikitet, vilket krävs för relationsdatabaser.
ID:t är en fysisk registreringspekare, det betyder ingenting, användaren ska inte se det. Men du (och andra) har gett det mening.
Vilket limmar dig till filens fysiska struktur, snarare än den logiska strukturen av datan. Vilket i sin tur komplicerar din kod.
Därför utan att ge dig en korrigerad
CREATE TABLE
kommandot, lämna ditt som det är, låt oss låtsas att ID:t och AVERAGE inte finns i filen.
En tredje post, som inte är relaterad till tillvägagångssätt, verkar som om du utifrån den angivna siffran, 10,58, vill ha Kilometer per liter, medan den aritmetik du har specificerat (Liter per 100 Km) kommer att ge 9,44. Om du vill ha ett genomsnitt av något slag är det bättre att ta reda på elementen först.
Lösning
(Code obsolete due to revision)
Reviderad fråga
Jag försökte få fram siffrorna du gav, medan frågan förblev förvirrad (observera kommentarerna om detta). Eftersom du har Reviderat din fråga, kravet är nu klart. Det verkar nu som om du vill ha (a) liter per 100 km [fortfarande inte ett "genomsnitt"], och (b) en total siffra för varje rekord [en sorts löpande totalsumma]. Använd i så fall den här koden.
Anmärkningarna ovan förblir giltiga och tillämpliga.
SELECT CARID,
DATETIME,
KM,
LI,
LPCK = ( LI_TOT / ( ( KM_LAST-KM_FIRST / 100 ) ) -- not stored
FROM (
-- create a Derived Table with KM_FIRST
SELECT CARID,
DATETIME,
-- not stored
KM_FIRST = (
SELECT MIN( KM ) -- get the first KM for car
FROM CONSUM
WHERE CARID = C.CARID
),
KM_LAST = (
SELECT MAX( KM ) -- get the last KM for car
FROM CONSUM
WHERE CARID = C.CARID
),
KM, -- KM for this row
LI, -- LI for this row
LI_TOT = (
SELECT SUM( LI ) -- get the total LI for car
FROM CONSUM
WHERE CARID = C.CARID
AND KM != ( -- exclude first LI for car
SELECT MIN( KM ) -- get the first KM for car
FROM CONSUM
WHERE CARID = C.CARID
)
)
FROM CONSUM C
) AS CONSUM_EXT
ORDER BY CARID,
DATETIME
Lägg märke till att jag manipulerar data, och bara data, inga fysiska fält, vi borde inte bry oss om de fysiska aspekterna av filen. Liter per 100 km (vad du kallar AVERAGE) lagras inte, och där undviks en Update Anomaly. Den totala siffran för varje post beräknas "i farten", endast vid visningstid.
Detta eliminerar också din /first entry
problem.
Naturligtvis CARID
är också meningslöst för användaren.
Kommentera gärna eller ställ frågor etc.
Hård lagring
Det finns många problem med att lagra ett värde som kan härledas. Detta är hårdkodning på datalagringsnivå. Visst, du kan använda en trigger för att lindra smärtan, men det fungerar fortfarande inte, eftersom (a) principen är bruten och (b) den bryter mot befintliga tekniska principer. T.ex. vad händer när LI för en enskild rad skrivs in felaktigt (t.ex. 700.17) och sedan korrigeras (t.ex. 70.17)? Alla efterföljande rader för den bilen är nu felaktiga och måste beräknas om och uppdateras. Så nu behöver du en Update trigger såväl som en Insert trigger. Cancer sammansätter sig själv.
Konceptet med en Update Anomaly, förbudet mot att lagra värden som kan härledas, har funnits med oss sedan 1970, av goda skäl. Vi undviker dem, av goda skäl.