商品とその販売スケジュールを管理するためのテーブル設計をするとき、販売スケジュールの情報を別テーブルに分離しておくと再利用性の高い作りに出来る場合があります。一つの設計パターンとしてメモしておきます。
例えば、以下の様な販売方法に対応したいとします。
- 同時に複数の商品を販売する
- 期間ごとに販売する商品の組み合わせ(商品セット)が異なる
- 一度販売した商品の組み合わせは以降も使いまわす場合がある
つまりこういったケースです。
- 1月に販売する商品
- 商品A
- 商品B
- 2月に販売する商品
- 商品C
- 3月に販売する商品(1月の商品セットの使い回し)
- 商品A
- 商品B
テーブル設計例
products テーブル(商品)
id
INT AUTO_INCREMENTname
VARCHAR COMMENT ‘商品名’
product_sets テーブル(商品セット)
id
INT AUTO_INCREMENTname
VARCHAR COMMENT ‘商品セット名’is_default
BOOL COMMENT ‘基本商品セットフラグ’
product_set_relations テーブル(商品セットに属する商品)
id
INT AUTO_INCREMENTproduct_set_id
INTproduct_id
INT
product_set_sale_schedules テーブル(商品セットの販売スケジュール)
id
INT AUTO_INCREMENTproduct_set_id
INTstart_datetime
DATETIME COMMENT ‘販売開始日時’end_datetime
DATETIME COMMENT ‘販売終了日時’
上記スキーマの解説
まず products
テーブルに商品情報を持ちます。商品の種類の数だけレコードが出来ます。
そして複数の商品をまとめた商品セットを product_sets
としてまとめ、その商品セットの販売期間の情報を product_set_sale_schedules
に持つという構成です。
product_set_relations
テーブルは多:多のリレーションを解消するための中間テーブルです。商品セットに属する商品一覧の情報を持ちます。
一度販売した商品セットは今後のスケジューリングでも使い回すことが出来ます。
もし期間に該当する商品セットがあった場合、それが優先して有効な商品セットとなりますが、該当するスケジュール情報が無かった場合は is_default
が立っている基本商品セットが有効になります。こうしておくことで該当する販売スケジュールのデータが無かった場合のフォールバックが可能となり、常に何かを販売し続けることができます。(その必要が無ければ不要)
また、過去の販売スケジュールの履歴はスケジュールテーブルに蓄積して残すことが出来るため、後から過去の販売スケジュールを確認することができます。
今回の設計パターンについて補足
今回は少し要件が特殊だと思うので、実際には要件に合わせて構成を見なおした方がいいと思います。(設計パターンとか書いておいてすみません。)
例えば今回用いた「商品セット」という概念は、商品の組み合わせの再利用をしやすくする一方で、細やかな組み合わせの変更を難しくしています。
再利用されるケースが少ない場合は商品セットテーブルを無くしてしまい、商品ごとにスケジュールを設定する構成にしたほうが柔軟に対応できるでしょう。
「運用でカバー」は悲しい
運用でカバーという名のもと無駄なデータが生まれていくのは設計者として悲しいことです。
要件をよく確認して適切にテーブル設計をしていきたいものです。