質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

データベース設計

データベース設計はデータベースの論理的や物理的な部分を特定する工程です。

Q&A

解決済

3回答

2128閲覧

RDBで商品の購入を表現するとき、トランザクションデータとして合計金額を持つべきか、各商品の単価を持つべきか

akadashi

総合スコア19

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

データベース設計

データベース設計はデータベースの論理的や物理的な部分を特定する工程です。

0グッド

1クリップ

投稿2020/09/25 14:31

編集2020/09/25 14:34

質問の内容

Q. 商品の購入という出来事を表現するため、下図のようにデータベースを設計したとします。このとき、購入テーブルのほうが「合計金額(税抜)」をカラムとして保持すべきでしょうか、それとも購入商品テーブルのほうが「購入時の単価」をカラムとして保持すべきでしょうか。
イメージ説明

なお、以下のような前提があるものとします。

  • ユーザによって商品の購入が行われると、その時点における商品テーブルのデータに基づき、購入テーブルと購入商品テーブルにデータが作成される。購入時の手数料や割引などは、金額調整テーブルのデータとして作成される(例 名目:手数料 金額:150)。
  • 購入テーブルと購入商品テーブルと金額調整テーブルはトランザクションデータテーブルであり、一度保存されたデータは、更新も削除もされない。
  • ユーザテーブルと商品テーブルはマスタであり、メンテナンスなどの過程で各データは更新されうる。また、論理削除されうるが、物理削除はされない。

質問の意図

ネット上で正規化手法の記事を読んでいると、ほとんどの場合が「合計金額(税抜)」を残し、「購入時の単価」(または小計)のカラムを削除しています。

個人的意見としては、「各商品の単価から合計金額を導出することはできるが、合計金額から各商品の単価を導出することはできない」と思うので、データベース設計の際には「合計金額(税抜)」よりも「購入時の単価」のほうを残しておいたほうが、後からそのデータがほしくなったときに都合がよいと感じます。

おそらく、ネット記事の例では「合計金額は各商品の単価×数量の和と一致しないケースがある」ということに配慮し、安全のために「合計金額(税抜)」のほうを残しているのだろうとは思うのですが、もとの非正規形のテーブルでは記録できていたはずの「購入時の単価」(または小計)のカラムを、正規化の過程で削除してしまうのは、情報無損失分解の原理に反しているようにも見えます。

このような操作は正規化のポリシーとして正しいのかどうか気になり、質問いたしました。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

「各商品の単価から合計金額を導出することはできるが、合計金額から各商品の単価を導出することはできない」

そのシステムの「合計金額」の意味するところによりますが「合計金額+消費税額」が最終的な「支払金額」となる場合、「合計金額」には「購入数量x単価の合計に対する割引処理」がされた金額が入る可能性を考慮すると、「単価から合計金額は導出可能である」という前提は崩れたりします。

まぁ「その場合は割引金額の列を作る」というのかもしれませんが、そこまでは具体的な仕様がわからないと何とも言えません。

そういう仕様的な部分を考慮しないとしても、一般的にトランザクション系のデータをとっておくか否かを迷う場合、「安全側に倒す」という意味で、多少冗長であってもデータはないよりあった方が良い場合が往々にしてあります。

後々の考慮漏れに対処できたり、何らかの不具合によるデータ欠損の場合に復旧する際のヒントになり得るからです。

もっとアプリケーション寄りの話なら、売上データのサマリを出力する際にいちいち集計をかけるのは余計な負荷となるため、冗長性を持たせてでもデータの取り扱いを楽にする、という意味でも、両方残しておくことは多いと思います。

また、「購入時の単価を削除する」という判断は基本的にないと思います。これがなくなると、購入時の明細を出力することが不可能になります。

そのシステムで明細が必要ない、あるいは別のデータで代替できる、という根拠があれば別ですが、通常は一番細かい粒度のデータを捨てて良いとはならないと思います。(それこそ導出可能なデータより重要なので)

まぁ、結局は具体的な仕様や設計思想、想定されるパフォーマンスの問題によるため、必ずこれが正解というものはありませんが、「両方残しておいた方が良いだろう」と思われるケースは多数あるものの、その全てが目の前のシステムに於いて「必要ない」と判断されるのであれば、最小限のデータだけ持っておけば良いんじゃないでしょうか。

投稿2020/09/25 22:41

編集2020/09/25 22:48
gentaro

総合スコア8949

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

akadashi

2020/09/29 05:57

さまざまな側面からご説明いただきありがとうございました。トランザクションデータについては、悩む場合は両方残しておいたほうがよさそうですね。
guest

0

「購入時の単価」は正規化の観点から残すべきもので、「合計金額(税抜)」は第1正規形での導出項目ですから排除対象です。

ですが、集計テーブルと同じ意味合いで正規化を緩める対象にもなり得ます。

項目的には、排除した場合の導出の機会と、排除しないで導出の結果を更新する機会を比べると、
件数的に前者が多いと思われるので、「合計金額(税抜)」も残すのをお薦めしておきます。

投稿2020/09/26 04:51

編集2020/09/26 05:49
sazi

総合スコア25195

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

難しいですね。
私は両方残しておきます。どちらかを選べと言われれば、
購入時の単価を残します。理由は質問者様と同じで合計は導出できるからです。

個人的にはトランザクション系のテーブルは、厳密に正規化をしないことにしています。
プログラムからの利用のしやすさや、記録を残すことを重視しています。
親子関係を意識しますね。

たいして、マスタは厳密に正規化するようにしています。
話しがそれてしまいましたが、私は両方を残したいですね。

投稿2020/09/25 14:58

Kaiser

総合スコア295

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問