私の意見では、質問を見たときに答えが完全ではないため、これを追加することが重要だと思います. 元の質問には適切に回答されていますが、ここに問題があります。したがって、以下に引用されている追加の質問のみを考慮します。
もう1つのことは、彼が支払いテーブルに合計金額を含めたかったことです.これは不要だと思います(製品の単価と数量を計算するだけです.). 彼は、システム管理全体にとって重要な借方および/または貸方を計算するためにその列が必要であり、トランザクションのバランスを取るために必要であると指摘しました。どう思うか教えてください。
この編集は面白い。これがお金を扱う取引システムであるという事実に基づいて、責任を負う必要があります。トランザクション、製品、価格、金額という基本的な用語をいくつか取り上げます。
その意味で、非正規化は非常に一般的であり、必要ですらあります。なんで?説明責任を負う必要があるからです。したがって、トランザクションが登録されると、変更されることはありません。それを修正する必要がある場合は、別の取引を行います。
はい、たとえば製品価格*金額*税などを計算できます。これは、正規化の意味で理にかなっています。ただし、関連するすべてのレコードを完全にロックダウンする必要があります。たとえば、products テーブルを見てみましょう。トランザクションの前に価格を変更した場合、トランザクションが発生したときに考慮に入れる必要があります。ただし、後で価格が変更された場合、取引には影響しません。
そのため、製品が変更される可能性があるため、単に transaction.product_id=products.id に参加することはできません。例:
2012-01-01 price = 10
2012-01-05 price = 20
Transaction happens here, we sell 10 items so 10 * 20 = 200
2012-01-06 price = 22
ここで、2012 年 1 月 10 日のトランザクションを検索するので、次のようにします。
SELECT
transactions.amount * products.price AS totalAmount
FROM transactions
INNER JOIN products on products.id=transactions.product_id
これは 10 * 22 = 220 となり、正しくありません。
したがって、2 つのオプションがあります。
products テーブルの更新を許可しないでください。したがって、そのテーブルをバージョン管理するため、すべてのレコードに対して、更新ではなく新しい INSERT を追加します。したがって、トランザクションは製品の正しいバージョンを指し続けます。
または、トランザクション テーブルにフィールドを追加するだけです。したがって、トランザクション テーブルに totalAmount を追加し、トランザクションが挿入されたときに (データベース トランザクションで) 計算して保存します。
はい、非正規化されていますが、それには正当な理由があり、説明責任があります。あなたはただ知っており、取引、ロックなどで検証されています.取引が発生した瞬間、価格= 20などの説明された製品に関連しています.
それに加えて、とにかくそれを行う必要がある場合、それは非正規化の良いことです。レポートを実行するのは非常に簡単です。月、年などの総取引額。すべて非常に簡単に計算できます。
正規化には、たとえば、二重ストレージがない、編集ポイントが 1 つであるなどの利点があります。ただし、この場合、トランザクション ログ データベースには許可されておらず、優先されないため、その概念は必要ありません。
トランザクションを、現実世界で起こった何かの登録と見なしてください。それは起こりました、あなたはそれを書き留めました。今は歴史を変えることはできません、それはそのまま書かれました。未来はそれを変えません、それは起こりました。