sql >> Databáze >  >> RDS >> Mysql

Jak sečíst nový a naposledy vložený záznam se stejným ID a vložit výsledek do nového záznamu

Přístup

Ve svém přístupu máte dvě chyby, což přináší složitost.

  1. Jakýkoli sloupec, který lze odvodit, například váš PRŮMĚR, by neměl být uložen.

    Pokud je uložen, tvoří duplicitní sloupec ... což vede k anomálii aktualizace, jak jste zažili vy. Smyslem normalizace je eliminovat duplicitu dat a tím eliminovat anomálie aktualizací. Také eliminuje složitý kód, jako je tento, stejně jako spouštěče atd.

    Vypočítat SUM(), AVG() atd. pouze v sadě výsledků , za běhu.

  2. Použití sloupců ID, což v podstatě znamená, že máte systém evidence záznamů, žádnou relační databázi. Aniž bych vyjmenovával mnoho problémů, které to způsobuje (udělal jsem to jinde), jen pojmenuji problém zde

    • máte nastavení ID.

    ID je ukazatel fyzického záznamu, neposkytuje jedinečnost řádku, jak je požadováno pro relační databáze.

    ID je ukazatel fyzického záznamu, nic neznamená, uživatel by ho neměl vidět. Ale vy (a ostatní) jste tomu dali smysl.

    Což vás přilepí k fyzické struktuře souboru, spíše než k logické struktuře dat. Což zase komplikuje váš kód.

    Proto bez poskytnutí opraveného CREATE TABLE příkaz, ponechte váš tak, jak je, předstírejme, že ID a PRŮMĚR v souboru neexistují.

Třetí položka, která nesouvisí s přiblížením, se zdá, že z uvedeného čísla, 10,58, chcete Kilometry na litr, zatímco aritmetika, kterou jste podrobně uvedla (litry na 100 km), dá 9,44. Pokud chcete nějaký průměr, je lepší nejprve zjistit jednotlivé prvky.

Řešení

    (Code obsolete due to revision)

Upravená otázka

Pokoušel jsem se získat údaje, které jste uvedl, zatímco otázka zůstala zmatená (v tomto smyslu si povšimněte komentářů). Protože jste Revidovali vaše otázka, požadavek je nyní jasný. Nyní se zdá, že chcete (a) litry na 100 km [stále to není "průměr"] a (b) celkové číslo pro každý rekord [druh průběžného součtu]. V takovém případě použijte tento kód.

Výše uvedené poznámky zůstávají platné a použitelné.

    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

Všimněte si, že manipuluji s daty a pouze s daty, bez fyzických polí, fyzické aspekty souboru by nás neměly zajímat. Litry na 100 km (to, čemu říkáte PRŮMĚR) se neukládají a nedochází k anomálii aktualizace. Celková hodnota pro každý záznam se vypočítá "za běhu", pouze v době zobrazení.

To také eliminuje váš /first entry problém.

Samozřejmě CARID stejně tak nemá pro uživatele žádný význam.

Prosím, neváhejte komentovat nebo klást otázky atd.

Ukládání na pevný disk

Existuje mnoho problémů s ukládáním hodnoty, kterou lze odvodit. Toto je pevné kódování na úrovni úložiště dat. Jistě, můžete použít spoušť ke zmírnění bolesti, ale stejně to nebude fungovat, protože (a) princip je porušen a (b) porušuje stávající inženýrské principy. Např. co se stane, když je LI pro jeden řádek nesprávně zadán (např. 700,17) a následně opraven (např. 70,17)? Všechny následující řádky pro daný vůz jsou nyní nesprávné a je třeba je znovu vypočítat a aktualizovat. Nyní tedy potřebujete spouštěč aktualizace a také spouštěč vložení. Samotné sloučeniny rakoviny.

Koncept anomálie aktualizací, zákaz ukládání hodnot, které lze odvodit, je s námi již od roku 1970, a to z dobrého důvodu. Z dobrého důvodu se jim vyhýbáme.



  1. Python psycopg2 cursor.fetchall() vrací prázdný seznam, ale cursor.rowcount je> 1

  2. Může se kontrolní omezení vztahovat k jiné tabulce? Věštec

  3. SQL – Pokročilé odstraňování duplicit pomocí ID NOT IN

  4. Jaký je encode(<columnName>, 'escape') ekvivalent PostgreSQL v jazyce Java?