sql >> Databasteknik >  >> RDS >> Mysql

Hur man summerar ny och senast infogade post med samma ID och infogar resultat i ny post

Tillvägagångssätt

Du har två fel i ditt tillvägagångssätt, vilket introducerar komplexitet.

  1. 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.

  2. 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.



  1. Kontrollera aktuellt FOREIGN_KEY_CHECKS-värde

  2. Få alla inlägg med summan av röster och om nuvarande användare röstade varje inlägg

  3. Stort heltalsfält i django-modeller

  4. Att använda TYPE =InnoDB i MySQL ger undantag