Tilgang
Du har to fejl i din tilgang, hvilket introducerer kompleksitet.
-
Enhver kolonne, der kan udledes, såsom din AVERAGE bør ikke blive opbevaret.
Hvis det er gemt, udgør det en dublet kolonne ... hvilket fører til en opdateringsanomali, som du oplever. Pointen med normalisering er at eliminere dataduplikering og dermed eliminere opdateringsanomalier. Det eliminerer også kompleks kode som denne, såvel som triggere osv.
Beregn SUM(), AVG() osv. i resultatsættet kun , i farten.
-
Brug af ID-kolonner, hvilket dybest set betyder, at du har et registreringssystem, ingen en relationel database. Uden at opregne de mange problemer, det forårsager (det har jeg gjort andre steder), skal du blot nævne problemet her
- du har en ID-tankegang.
ID'et er en fysisk registreringsmarkør, det giver ikke række-entydighed, som det kræves for relationelle databaser.
ID'et er en fysisk registreringsmarkør, det betyder ingenting, brugeren skal ikke se det. Men du (og andre) har givet det mening.
Hvilket limer dig til filens fysiske struktur, snarere end den logiske struktur af dataene. Hvilket igen komplicerer din kode.
Derfor uden at give dig en rettet
CREATE TABLE
kommando, lad os lade som om ID'et og AVERAGE ikke eksisterer i filen.
Et tredje punkt, der ikke er relateret til tilgang, ser ud til, at ud fra det angivne tal, 10,58, vil du have kilometer pr. liter, hvorimod den aritmetik, du har detaljeret (liter pr. Hvis du vil have et gennemsnit af en eller anden art, er det bedre at finde ud af elementerne først.
Løsning
(Code obsolete due to revision)
Revideret spørgsmål
Jeg forsøgte at få de tal, du gav, mens spørgsmålet forblev forvirret (bemærk kommentarerne herom). Da du har revideret dit spørgsmål er kravet nu klart. Det ser nu ud til, at du ønsker (a) liter pr. 100 km [stadig ikke et "gennemsnit"], og (b) et samlet tal for hver rekord [en slags løbende total]. I så fald skal du bruge denne kode.
Ovenstående bemærkninger forbliver gyldige og gældende.
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
Bemærk, at jeg manipulerer dataene, og kun dataene, ingen fysiske felter, vi burde være ligeglade med de fysiske aspekter af filen. Liter pr. 100 km (det du kalder AVERAGE) lagres ikke, og der undgås en Update Anomaly. Det samlede tal for hver post beregnes "on the fly", kun på visningstidspunktet.
Dette eliminerer også din /first entry
problem.
Selvfølgelig, CARID
er også meningsløst for brugeren.
Du er velkommen til at kommentere eller stille spørgsmål osv.
Hård lagring
Der er mange problemer med at gemme en værdi, der kan udledes. Dette er hårdkodning på datalagringsniveau. Selvfølgelig kan du bruge en trigger til at lindre smerten, men det virker stadig ikke, fordi (a) princippet er brudt og (b) det bryder med eksisterende tekniske principper. For eksempel. hvad sker der, når LI for en enkelt række er indtastet forkert (f.eks. 700.17) og efterfølgende rettet (f.eks. 70.17)? Alle de efterfølgende rækker for den bil er nu forkerte og skal genberegnes og opdateres. Så nu har du brug for en Update trigger samt en Insert trigger. Kræft sammensætter sig selv.
Konceptet med en opdateringsanomali, forbuddet mod at lagre værdier, der kan udledes, har været hos os siden 1970, med god grund. Vi undgår dem med god grund.