32081


たとえなのですが、ショッピングサイトを作っているとします。  
そして化粧品とゲームが買えるとします。  
また買った物の履歴を見れる機能もあるとします。

テーブルの設計をするとき、自分だとこのような場合は、  
履歴テーブル、化粧品テーブル、ゲームテーブル  
と作ります。

化粧品テーブルのカラムは  
id, 値段、材料  
ゲームテーブルのカラムは  
id, 値段、対応ハードウェアとします。

ただここで問題なのは履歴テーブルのカラムです。  
単純に考えるとこう考えました。  
id, 化粧品id, ゲームid, 時間

しかしこの構造には問題があります。  
化粧品idとゲームidのカラムはどちらか一つしか使われないため、後はnullが入ることになります。  
さらに、玩具や食品などを追加すると空のカラムが増大していきます。

どのように設計するのが良いでしょうか？ご回答よろしくお願いします。


CC BY-SA 3.0
2017-01-23T06:14:53.680
32075
2017-01-23T09:26:08.350
2017-01-23T06:49:15.330
20353
20353
question
database データベース設計
複数のテーブルの参照を、一つのカラムで管理するためには？


こういったケースでは、ひとつのテーブルで管理するよりきちんとテーブルを分けて整理するほうが好ましいです。

化粧品テーブルとゲームソフトテーブルで共通の要素（商品名）を抽出した、商品テーブルを作りましょう。  
化粧品なら

  * 材料

ゲームソフトなら

  * 対応ハード
  * ジャンル
  * 対象年齢

といったことは、 **商品に付属する情報とみなせる** ので、付帯情報をまとめるテーブルを作りましょう。

これで、履歴テーブルからnullのカラムを追い出すことができます。

**商品カテゴリテーブル**

[code]

    id, カテゴリ名
    1,  化粧品
    2,  ゲームソフト
    
[/code]

**付帯情報種別テーブル**

[code]

    id, 商品カテゴリid, 付帯情報種別名
    1,  1,           材料
    2,  2,           対応ハードウェア
    3,  2,           ジャンル
    4,  2,           対象年齢
    
[/code]

**商品テーブル**

[code]

    id, 商品名
    1,  化粧品A
    2,  ゲームソフトB
    
[/code]

**付帯情報テーブル**

[code]

    id, 商品id, 付帯情報種別id, 内容
    1,  1,     1,            きれいになるパウダー
    2,  2,     2,            イケてるハード
    3,  2,     3,            はやりのジャンル
    4,  2,     4,            全年齢
    
[/code]

**履歴テーブル**

[code]

    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
    
[/code]

例えでは付帯情報テーブルの"内容"に文字列を直接入れていますが、この内容も別テーブルに切り出しても良いでしょう。


CC BY-SA 3.0
2017-01-23T09:06:08.563
32081
2017-01-23T09:06:08.563
14973
32075
answer


もし「テーブルを利用するコード側で頑張り尽くす」というのであれば、外部キー制約を使わずテーブル名をレコードに書く、という選択肢を選ぶことができます。

**履歴テーブル**

[code]

    id, 商品id, テーブル名,  対象id, 時間
    1,  1,     化粧品,     1       2017-01-01 12:00:00
    2,  2,     ゲームソフト,  1       2017-01-01 13:00:00
    3,  3,     ゲームソフト,  2       2017-01-01 14:00:00
    
[/code]


CC BY-SA 3.0
2017-01-23T09:26:08.350
32083
2017-01-23T09:26:08.350
14973
32075
answer