sql >> Database >  >> RDS >> Mysql

Hoe nieuwe en laatst ingevoegde invoer met dezelfde ID optellen en resultaat in nieuwe invoer invoegen?

Aanpak

Je hebt twee fouten in je aanpak, wat complexiteit introduceert.

  1. Elke kolom die kan worden afgeleid, zoals uw GEMIDDELDE, mag niet worden opgeslagen.

    Als het wordt opgeslagen, vormt het een dubbele kolom ... wat leidt tot een updateafwijking, zoals u ervaart. Het doel van normalisatie is het elimineren van gegevensduplicatie en dus het elimineren van updateafwijkingen. Het elimineert ook complexe code zoals deze, evenals triggers, enz.

    Bereken SUM(), AVG(), etc, in de resultaatset alleen , tijdens de vlucht.

  2. Gebruik van ID-kolommen, wat in feite betekent dat u een Record Filing System heeft, geen relationele database. Zonder de vele problemen op te sommen die het veroorzaakt (dat heb ik elders gedaan), noem ik het probleem hier gewoon

    • je hebt een ID-mentaliteit.

    De ID is een fysieke recordaanwijzer en biedt geen uniekheid van rijen, zoals vereist voor relationele databases.

    De ID is een fysieke recordaanwijzer, het betekent niets, de gebruiker zou het niet moeten zien. Maar jij (en anderen) hebben er betekenis aan gegeven.

    Waardoor je vastzit aan de fysieke structuur van het bestand, in plaats van aan de logische structuur van de gegevens. Wat op zijn beurt je code compliceert.

    Daarom, zonder u een gecorrigeerde CREATE TABLE . te geven commando, laat het uwe zoals het is, laten we doen alsof de ID en het GEMIDDELDE niet in het bestand voorkomen.

Een derde item, niet gerelateerd aan benadering, het lijkt erop dat uit het gegeven cijfer, 10,58, je Kilometer per liter wilt, terwijl de rekenkunde die je hebt gedetailleerd (Liters per 100 Km) 9,44 zal opleveren. Als je toch een soort gemiddelde wilt, kun je beter eerst de elementen uitzoeken.

Oplossing

    (Code obsolete due to revision)

Herziene vraag

Ik probeerde de cijfers te krijgen die u gaf, terwijl de vraag verward bleef (let op de opmerkingen in die zin). Aangezien je Revised hebt uw vraag, de eis is nu duidelijk. Het lijkt er nu op dat je (a) Liters per 100 Km [nog steeds geen "gemiddelde"] wilt, en (b) een totaalcijfer voor elk record [een soort lopend totaal]. Gebruik dan deze code.

Bovenstaande opmerkingen blijven geldig en van toepassing.

    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

Merk op dat ik de gegevens manipuleer, en alleen de gegevens, geen fysieke velden, we zouden ons niets moeten aantrekken van de fysieke aspecten van het bestand. Liters per 100 Km (wat je GEMIDDELDE noemt) wordt niet opgeslagen, en daar wordt een Update Anomaly vermeden. Het totale cijfer voor elk record wordt "on the fly" berekend, alleen tijdens de weergavetijd.

Dit elimineert ook uw /first entry probleem.

Natuurlijk, CARID ook is zinloos voor de gebruiker.

Aarzel niet om commentaar te geven of vragen te stellen, enz.

Moeilijke opslag

Er zijn veel problemen met het opslaan van een waarde die kan worden afgeleid. Dit is harde codering op het niveau van gegevensopslag. Natuurlijk kun je een trigger gebruiken om de pijn te verlichten, maar het zal nog steeds niet werken, omdat (a) het principe is verbroken en (b) het in strijd is met bestaande technische principes. bijv. wat gebeurt er als de LI voor een enkele rij verkeerd wordt ingevoerd (bijv. 700.17) en vervolgens wordt gecorrigeerd (bijv. 70.17)? Alle volgende rijen voor die auto zijn nu onjuist en moeten opnieuw worden berekend en bijgewerkt. Dus nu heb je zowel een Update-trigger als een Insert-trigger nodig. Kanker vormt zichzelf.

Het concept van een Update Anomaly, het verbod om waarden op te slaan die kunnen worden afgeleid, is niet voor niets sinds 1970 bij ons. We vermijden ze om een ​​goede reden.



  1. Als u de ACL van Symfony gebruikt, is het dan beter om een ​​JOIN-query of een IN-arrayquery te gebruiken?

  2. Verbinding maken met Microsoft Access in IRI Workbench

  3. Maak onderscheid tussen NULL's bij gebruik van group by ... met rollup

  4. ORA-01652:kan tijdelijk segment niet uitbreiden met 128 in tabelruimte SYSTEEM:Hoe verlengen?