sql >> Database teknologi >  >> RDS >> Mysql

Hvordan man summerer ny og sidst indsat post med samme ID og indsætter resultat i ny post

Tilgang

Du har to fejl i din tilgang, hvilket introducerer kompleksitet.

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

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



  1. Neo4j - Opret en node ved hjælp af Cypher

  2. ORDER BY RAND()-funktionen tager lang tid at udføre i mysql

  3. 3 måder at få sproget for den aktuelle session i SQL Server (T-SQL)

  4. Hvordan påvirker NULL-værdier ydeevnen i en databasesøgning?