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

Come sommare la nuova voce e l'ultima inserita con lo stesso ID e inserire il risultato in una nuova voce

Approccio

Hai due errori nel tuo approccio, che introduce complessità.

  1. Qualsiasi colonna che può essere derivata, come la tua MEDIA, deve non essere immagazzinato.

    Se è memorizzato, costituisce una colonna duplicata ... che porta a un'anomalia di aggiornamento, come stai riscontrando. Lo scopo della normalizzazione è eliminare la duplicazione dei dati e quindi eliminare le anomalie di aggiornamento. Elimina anche codice complesso come questo, trigger, ecc.

    Calcola SUM(), AVG() e così via nel set di risultati solo , al volo.

  2. Utilizzo di colonne ID, che in pratica significa che hai un sistema di archiviazione dei record, non un database relazionale. Senza enumerare i molti problemi che provoca (l'ho fatto altrove), nominando semplicemente il problema qui

    • hai una mentalità ID.

    L'ID è un puntatore a un record fisico, non fornisce l'univocità della riga, come richiesto per i database relazionali.

    L'ID è un puntatore a un record fisico, non significa nulla, l'utente non dovrebbe vederlo. Ma tu (e altri) gli avete dato un significato.

    Che ti incolla alla struttura fisica del file, piuttosto che alla struttura logica dei dati. Il che a sua volta complica il tuo codice.

    Pertanto, senza darti un CREATE TABLE corretto comando, lasciando il tuo così com'è, facciamo finta che l'ID, e la MEDIA, non esistano nel file.

Una terza voce, non relativa all'approccio, sembra che dalla cifra data, 10,58, si vogliano Chilometri per litro, mentre l'aritmetica che hai dettagliato (Litri per 100 Km) produrrà 9,44. Se vuoi una media di qualche tipo, è meglio capire prima gli elementi.

Soluzione

    (Code obsolete due to revision)

Domanda modificata

Stavo cercando di ottenere le cifre da lei fornite, mentre la domanda rimaneva confusa (notare i commenti in tal senso). Dal momento che hai Rivisto la tua domanda, il requisito ora è chiaro. Ora sembra che tu voglia (a) litri per 100 Km [ancora non una "media"] e (b) una cifra complessiva per ogni record [una specie di totale parziale]. In tal caso, utilizzare questo codice.

Le note di cui sopra restano valide ed applicabili.

    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

Si noti che sto manipolando i dati e solo i dati, nessun campo fisico, non dovremmo preoccuparci degli aspetti fisici del file. I litri per 100 Km (quello che chiami MEDIA) non vengono memorizzati e lì viene evitata un'anomalia di aggiornamento. La cifra complessiva per ogni record viene calcolata "al volo", solo al momento della visualizzazione.

Questo elimina anche il tuo /first entry problema.

Naturalmente, CARID inoltre è privo di significato per l'utente.

Sentiti libero di commentare o porre domande, ecc.

Memorizzazione difficile

Ci sono molti problemi con la memorizzazione di un valore che può essere derivato. Questo è l'hardcoding a livello di archiviazione dei dati. Certo, puoi usare un trigger per alleviare il dolore, ma non funzionerà comunque, perché (a) il principio è infranto e (b) viola i principi ingegneristici esistenti. Per esempio. cosa succede quando il LI di una singola riga viene inserito in modo errato (es. 700.17) e successivamente corretto (es. 70.17)? Tutte le righe successive per quell'auto ora non sono corrette e devono essere ricalcolate e aggiornate. Quindi ora hai bisogno di un trigger di aggiornamento e di un trigger di inserimento. Il cancro si compone da solo.

Il concetto di anomalia di aggiornamento, il divieto di memorizzare valori che possono essere derivati, è presente dal 1970, per una buona ragione. Li evitiamo, per una buona ragione.