質問: たとえなのですが、ショッピングサイトを作っているとします。 そして化粧品とゲームが買えるとします。 また買った物の履歴を見れる機能もあるとします。 テーブルの設計をするとき、自分だとこのような場合は、 履歴テーブル、化粧品テーブル、ゲームテーブル と作ります。 化粧品テーブルのカラムは id, 値段、材料 ゲームテーブルのカラムは id, 値段、対応ハードウェアとします。 ただここで問題なのは履歴テーブルのカラムです。 単純に考えるとこう考えました。 id, 化粧品id, ゲームid, 時間 しかしこの構造には問題があります。 化粧品idとゲームidのカラムはどちらか一つしか使われないため、後はnullが入ることになります。 さらに、玩具や食品などを追加すると空のカラムが増大していきます。 どのように設計するのが良いでしょうか?ご回答よろしくお願いします。
回答: こういったケースでは、ひとつのテーブルで管理するよりきちんとテーブルを分けて整理するほうが好ましいです。 化粧品テーブルとゲームソフトテーブルで共通の要素(商品名)を抽出した、商品テーブルを作りましょう。 化粧品なら * 材料 ゲームソフトなら * 対応ハード * ジャンル * 対象年齢 といったことは、**商品に付属する情報とみなせる**ので、付帯情報をまとめるテーブルを作りましょう。 これで、履歴テーブルからnullのカラムを追い出すことができます。 **商品カテゴリテーブル** ``` id, カテゴリ名 1, 化粧品 2, ゲームソフト ``` **付帯情報種別テーブル** ``` id, 商品カテゴリid, 付帯情報種別名 1, 1, 材料 2, 2, 対応ハードウェア 3, 2, ジャンル 4, 2, 対象年齢 ``` **商品テーブル** ``` id, 商品名 1, 化粧品A 2, ゲームソフトB ``` **付帯情報テーブル** ``` id, 商品id, 付帯情報種別id, 内容 1, 1, 1, きれいになるパウダー 2, 2, 2, イケてるハード 3, 2, 3, はやりのジャンル 4, 2, 4, 全年齢 ``` **履歴テーブル** ``` id, 商品id, 時間 1, 1, 2017-01-01 12:00:00 2, 2, 2017-01-01 13:00:00 3, 2, 2017-01-01 14:00:00 ``` 例えでは付帯情報テーブルの"内容"に文字列を直接入れていますが、この内容も別テーブルに切り出しても良いでしょう。