はじめに
楽々ERDレッスンを読んだので、重要だと思った点についてまとめ。
- One Fact in One Place
- ビジネスの視点から正規化
One Fact in One Placeについて
データベース設計の基本的な考え方がOne Fact in One Placeである。
日本語では「1つの事実が1つの場所にのみ存在する」ということ。
これを実現するための一つの手法として、データベースの正規化が挙げられる。
正規化というと、1つの事実を2つ以上の場所に置かない1ことを想像してしまいがちである。
しかし、2つ以上の事実を1つの場所に置かないことも重要だ。
2つ以上の事実を1つの場所に置いた状態
具体例を交えて考えてみる。
社員というテーブルを例に考える。
上記のテーブルでは、退職区分というカラムがあり、現役の社員なのか退職済みの社員なのかという情報を持っている。
現役社員の場合は、退職日がnullとなる。
退職済みの社員の場合は、セキュリティの観点から名前を保持しないため姓名がnullとなり、退職日に値が入る。
社員という一つのくくりで表現しようとしているが、社員には現役と退職済みという2つの種類があり、2つの事実を1つのテーブルの中に持ってしまっている。
区分というカラムによって、レコードの意味が変わってしまうという問題が発生している。
解決するためには、One Fact in One Placeを進めていけば良い。
このようにすれば、現役社員と退職済社員の2つを別のテーブルで管理することができる。
しかし、これだけでは十分ではない。退職済社員に着目すると、退職済社員というリソースの情報と、退職をするというイベントの情報が1つのテーブルにまとまっている。
これらを分解すると、
のようになる。
ビジネスの視点から正規化する
テーブルをわけて重複を排除していくことが正規化ではない。
正規化とは、ビジネスの視点から情報を整理していくことである。
例として商品の売上を管理するということを考える。
前提として今回の説明と関係ない項目は極力排除してある。
商品テーブルに単価を持たせているため、売上明細テーブルには商品の金額を持たせていない。
また、商品テーブルの単価と売上明細テーブルの数量を見れば合計金額は導出できるため、売上テーブルに合計金額は持たせていない。
テーブルの正規化というと上記のように、「持たせなくていいものをできるだけ持たせない」ということを想像してしまいがちである。
しかし、これが常に正しいとは限らない。
例えば、「今回のみ、この商品に関しては割引をして売る」ということが発生する場合、上記のテーブルでは表現することができない。この場合は、売上明細テーブルに販売価格を持つことが正しい。
あるいは「全体の売上金額から端数を割引する」ということが発生する場合、売上テーブルに割引後の合計金額を持つことが正しい。
このように、ビジネスで起こり得ることも加味したうえでテーブル設計を行う必要があり、ただ、テーブルをわけて重複を排除するのみが正規化ではない。
参考
-
例えば商品の売上の管理をする場合、価格を商品テーブルと売上テーブルに持たせてしまうと、価格という1つの事実を2つの場所で持っていることになる ↩