sql >> データベース >  >> RDS >> Mysql

同じIDの新しいエントリと最後に挿入されたエントリを合計し、結果を新しいエントリに挿入する方法

    アプローチ

    アプローチに2つのエラーがあり、複雑さが生じます。

    1. AVERAGEなど、派生可能な列はすべきではありません 保存されます。

      保存されている場合、それは重複する列を構成します...これはあなたが経験しているように更新異常につながります。正規化のポイントは、データの重複を排除し、更新の異常を排除することです。また、このような複雑なコードやトリガーなども排除されます。

      結果セットのSUM()、AVG()などをのみ計算します。 、オンザフライ。

    2. ID列の使用。これは、基本的に、リレーショナルデータベースではなく、レコードファイリングシステムがあることを意味します。それが引き起こす多くの問題を列挙することなく(私は他の場所でそれを行いました)、ここで問題に名前を付けるだけです

      • あなたにはIDの考え方があります。

      IDは物理レコードポインタであり、リレーショナルデータベースで必要とされる行の一意性を提供しません。

      IDは物理レコードポインタであり、何の意味もありません。ユーザーには表示されません。しかし、あなた(そして他の人)はそれに意味を与えました。

      これは、データの論理構造ではなく、ファイルの物理構造に接着します。これにより、コードが複雑になります。

      したがって、修正されたCREATE TABLEを提供することなく コマンドをそのままにして、IDとAVERAGEがファイルに存在しないように見せかけましょう。

    アプローチに関係のない3番目の項目は、与えられた図10.58から、1リットルあたりのキロメートルが必要なようですが、詳細な計算(100 Kmあたりのリットル)は9.44を生成します。ある種の平均が必要な場合は、最初に要素を把握することをお勧めします。

    ソリューション

        (Code obsolete due to revision)
    

    改訂された質問

    質問が混乱したままで、私はあなたが与えた数字を取得しようとしていました(その趣旨のコメントに注意してください)。 改訂があるので あなたの質問、要件は今明確です。これで、(a)100 Kmあたりのリットル[まだ「平均」ではない]、および(b)各レコードの全体的な数値[一種の累計]が必要なようです。その場合は、このコードを使用してください。

    上記の注記は引き続き有効であり、適用されます。

        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
    

    私がデータを操作していることに注意してください。物理フィールドではなく、データのみを操作しているので、ファイルの物理的な側面を気にする必要はありません。 100 Kmあたりのリットル(平均と呼んでいるもの)は保存されず、更新異常が回避されます。各レコードの全体的な数値は、表示時にのみ「オンザフライ」で計算されます。

    これにより、/first entryも削除されます 問題。

    もちろん、CARID 同様に、ユーザーにとっても無意味です。

    コメントや質問などもお気軽にどうぞ。

    ハードストレージ

    導出可能な値の保存には多くの問題があります。これは、データストレージレベルでのハードコーディングです。確かに、トリガーを使用して痛みを和らげることはできますが、(a)原則が破られており、(b)既存のエンジニアリング原則に違反しているため、それでも機能しません。例えば。単一行のLIが誤って入力され(例:700.17)、その後修正された場合(例:70.17)はどうなりますか?その車の後続のすべての行は正しくないため、再計算して更新する必要があります。したがって、ここで、更新トリガーと挿入トリガーが必要です。がん化合物自体。

    更新異常の概念、つまり導出可能な値の保存の禁止は、正当な理由で1970年以来私たちにありました。正当な理由で、それらを避けます。



    1. クエリ制約で日付を正しく処理する方法

    2. WHERE句のオプションの引数

    3. JDBCの基本概念、プーリングとスレッド化

    4. グループ別のSQLServer累積合計