Přístup
Ve svém přístupu máte dvě chyby, což přináší složitost.
-
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.
-
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.