Mysql
 sql >> Datenbank >  >> RDS >> Mysql

So summieren Sie den neuen und den zuletzt eingefügten Eintrag mit derselben ID und fügen das Ergebnis in einen neuen Eintrag ein

Ansatz

Sie haben zwei Fehler in Ihrem Ansatz, was die Komplexität erhöht.

  1. Jede Spalte, die abgeleitet werden kann, wie z. B. Ihr AVERAGE, sollte nicht sein gespeichert werden.

    Wenn es gespeichert wird, stellt es eine doppelte Spalte dar ... was zu einer Update-Anomalie führt, wie Sie es erleben. Der Sinn der Normalisierung besteht darin, Datenduplizierung und damit Aktualisierungsanomalien zu eliminieren. Es eliminiert auch komplexen Code wie diesen sowie Trigger usw.

    Berechnen Sie SUM(), AVG() usw. nur in der Ergebnismenge , spontan.

  2. Verwendung von ID-Spalten, was im Grunde bedeutet, dass Sie ein Datensatzablagesystem haben, keine relationale Datenbank. Ohne die vielen Probleme aufzuzählen, die es verursacht (das habe ich an anderer Stelle getan), nenne ich hier einfach das Problem

    • Sie haben eine ID-Denkweise.

    Die ID ist ein physischer Datensatzzeiger, sie bietet keine Zeileneindeutigkeit, wie es für relationale Datenbanken erforderlich ist.

    Die ID ist ein physischer Datensatzzeiger, sie bedeutet nichts, der Benutzer sollte sie nicht sehen. Aber Sie (und andere) haben ihm Bedeutung gegeben.

    Was Sie eher an die physische Struktur der Datei als an die logische Struktur der Daten bindet. Was wiederum Ihren Code verkompliziert.

    Daher ohne Ihnen eine korrigierte CREATE TABLE zu geben Lassen Sie uns unter Beibehaltung Ihres unveränderten Befehls so tun, als ob die ID und der AVERAGE nicht in der Datei vorhanden sind.

Ein dritter Punkt, der sich nicht auf die Annäherung bezieht, es scheint, dass Sie aus der angegebenen Zahl, 10,58, Kilometer pro Liter wollen, während die Arithmetik, die Sie detailliert haben (Liter pro 100 km), 9,44 ergibt. Wenn Sie einen Mittelwert wollen, ist es besser, zuerst die Elemente herauszufinden.

Lösung

    (Code obsolete due to revision)

Überarbeitete Frage

Ich habe versucht, die von Ihnen angegebenen Zahlen zu erhalten, während die Frage verwirrt blieb (beachten Sie die entsprechenden Kommentare). Da haben Sie überarbeitet Deine Frage, die Anforderung ist jetzt klar. Es scheint jetzt, dass Sie (a) Liter pro 100 km [immer noch kein "Durchschnitt"] und (b) eine Gesamtzahl für jeden Rekord [eine Art laufende Summe] wollen. Verwenden Sie in diesem Fall diesen Code.

Die vorstehenden Hinweise bleiben gültig und anwendbar.

    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

Beachten Sie, dass ich die Daten manipuliere, und nur die Daten, keine physischen Felder, wir sollten uns nicht um die physischen Aspekte der Datei kümmern. Liter pro 100 km (was Sie AVERAGE nennen) wird nicht gespeichert, und es wird eine Update-Anomalie vermieden. Die Gesamtzahl für jeden Datensatz wird "on the fly" nur zum Zeitpunkt der Anzeige berechnet.

Damit entfällt auch Ihr /first entry Problem.

Natürlich CARID ist für den Benutzer bedeutungslos.

Bitte fühlen Sie sich frei, zu kommentieren oder Fragen zu stellen usw.

Feste Speicherung

Es gibt viele Probleme beim Speichern eines Werts, der abgeleitet werden kann. Dies ist Hardcoding auf der Ebene der Datenspeicherung. Sicher, Sie können einen Auslöser verwenden, um den Schmerz zu lindern, aber es funktioniert immer noch nicht, weil (a) das Prinzip gebrochen ist und (b) es gegen bestehende technische Prinzipien verstößt. Z.B. Was passiert, wenn der LI für eine einzelne Zeile falsch eingegeben wird (z. B. 700,17) und anschließend korrigiert wird (z. B. 70,17)? Alle nachfolgenden Zeilen für dieses Auto sind nun falsch und müssen neu berechnet und aktualisiert werden. Jetzt brauchen Sie also sowohl einen Update-Trigger als auch einen Insert-Trigger. Krebsverbindungen selbst.

Das Konzept einer Update-Anomalie, das Verbot der Speicherung von Werten, die abgeleitet werden können, gibt es aus gutem Grund seit 1970. Wir vermeiden sie aus gutem Grund.