- PR -

1対1関連のテーブル設計について

投稿者投稿内容
nikori
会議室デビュー日: 2008/03/13
投稿数: 11
投稿日時: 2008-03-24 03:55
お世話になります。

テーブル設計についてご意見をお聞かせください。

【環境】
HSQLDB 1.8.0

次の2つのテーブルがあり、
カテゴリ(CATEGORY)テーブルと商品(ITEM)テーブルは1対多の関係です。
コード:
create table CATEGORY (
  ID  bigint,
  NAME varchar(32) not null,
  primary key(ID)
);

create table ITEM (
  ID bigint,
  NAME varchar(32) not null,
  CATEGORY_ID bigint not null, // CATEGORYテーブルへのFK
  primary key(ID)
);



これに次の要件を加えたいと思っています。
・1つのカテゴリに最大1つの商品を「注目商品」としてマークすることができる。

そして、次のような画面の表示を考えています。
コード:
【カテゴリ一覧画面】
(カテゴリ名, カテゴリ内登録商品数, 注目商品があれば注目商品名を表示)
をカテゴリの数だけ繰り返し表示。

【商品詳細画面】
(商品名, カテゴリ名, 注目商品なら「注目商品」と表示)



この場合、注目商品かどうかをどのようにテーブルで表現するのがよいのでしょうか?

【案1】
ITEMテーブルにその商品が注目商品かどうかを示すカラム(boolean型)を設ける。
ただ、この方法だと「1つのカテゴリに最大1つの注目商品」という要件を
DBの制約で保証できない。

【案2】
CATEGORYテーブルにITEMテーブルへの外部キーであり、
nullableなカラム(NOTICE_ITEM_ID)を設ける。
ただこの場合、双方のテーブルが互いに外部参照することになる。
このような構造はおかしいのか?

【案3】
次のような中間テーブルを設ける。
コード:
create table NOTICE_ITEM (
  CATEGORY_ID bigint,       // CATEGORYテーブルへのFK
  ITEM_ID bigint not null,  // ITEMテーブルへのFK
  primary key(CATEGORY_ID)

);



まとめますと、
(1)【案2】のように相互に外部参照する構造はありえないのでしょうか?
(2)要件を満たすには【案3】を採用すべきなのでしょうか?
それとも別のテーブル構造をとるべきでしょうか?
ご意見よろしくお願いします。
Anthyhime
ぬし
会議室デビュー日: 2002/09/10
投稿数: 437
投稿日時: 2008-03-24 07:51
案2でしょうね、案3は案2とほぼ同じことをしてます。
引用:
【案2】
CATEGORYテーブルにITEMテーブルへの外部キーであり、
nullableなカラム(NOTICE_ITEM_ID)を設ける。
ただこの場合、双方のテーブルが互いに外部参照することになる。
このような構造はおかしいのか?


おかしくありません。問題ないです。
忠犬
大ベテラン
会議室デビュー日: 2006/05/01
投稿数: 109
投稿日時: 2008-03-24 08:37
HSQLDBについて詳しくないですが、、、

引用:

【案1】
ITEMテーブルにその商品が注目商品かどうかを示すカラム(boolean型)を設ける。
ただ、この方法だと「1つのカテゴリに最大1つの注目商品」という要件を
DBの制約で保証できない。



コード:
create unique index ITEMIDX on ITEM(CATEGORY_ID,NOTICE_ITEM_FLG)



のような重複禁止の複合インデクス(マルチカラムインデクス)を定義すればいいの
では?
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2008-03-24 12:05
引用:

nikoriさんの書き込み (2008-03-24 03:55) より:
これに次の要件を加えたいと思っています。
・1つのカテゴリに最大1つの商品を「注目商品」としてマークすることができる。


引用:

nikoriさんの書き込み (2008-03-24 03:55) より:
まとめますと、
(1)【案2】のように相互に外部参照する構造はありえないのでしょうか?
(2)要件を満たすには【案3】を採用すべきなのでしょうか?


「案2」は、「1つのカテゴリに最大1つの商品」という制約をカテゴリーが管理するために、カテゴリが商品を参照していると考えることができます。ですから、カテゴリと商品が相互に参照しあうのは特に問題ではないと思います。
「案1」も、外部制約としては参照はないかもしれません。しかし、DB上での制約であってもアプリケーションでの見かけ上の制約であっても、そういう制約をかける以上、暗に参照があるとみなすほうが良いかもしれません。
よっしー
大ベテラン
会議室デビュー日: 2007/05/17
投稿数: 143
投稿日時: 2008-03-24 12:42
「最大1つ」という要件が今後も守られるなら案2、増えそうなら案1。
注目商品にその他の情報(期間とか)が必要なら案3が良いと思います。
indigo-x
大ベテラン
会議室デビュー日: 2008/02/21
投稿数: 207
お住まい・勤務地: 太陽の塔近く
投稿日時: 2008-03-24 13:08
私なら「案1」です(暗黙的に制約があると同じ意見です)

しかも「注目商品」はかなりゆるい仕様だと思います。

(もし突っ込むだったら、
  誰が決めるねん!
   複数あったらあかんのか!
    私こっちの方がおすすめ!)
だっちょ
大ベテラン
会議室デビュー日: 2006/12/05
投稿数: 115
投稿日時: 2008-03-24 15:23
疑問に思っていることがあったので、便乗して質問してみます。
最大1つだったら案2と3はほぼ同じなんでしょうが、今週の注目ランキングみたいな1対多の順序付きリストにする場合は、案2を拡張してNOTICE_ITEM_IDSでIDリストをあらわすデータを格納したのでよいのでしょうか?
1対多で多が100とかの場合、中間テーブルを作った場合、元のテーブルより巨大な中間テーブルになって、スピードの点でも問題があるような気がしているのですが。
(それをやめただけで2倍のスピードになったので)
 ということで私は案2してます。
よっしー
大ベテラン
会議室デビュー日: 2007/05/17
投稿数: 143
投稿日時: 2008-03-24 17:41
引用:

だっちょさんの書き込み (2008-03-24 15:23) より:
1対多で多が100とかの場合、中間テーブルを作った場合、元のテーブルより巨大な中間テーブルになって、スピードの点でも問題があるような気がしているのですが。
(それをやめただけで2倍のスピードになったので)
 ということで私は案2してます。


複数(100個とか)ある場合でも、案2を使うということですか?
NOTICE_ITEM_ID1、NOTICE_ITEM_ID2、NOTICE_ITEM_ID3…
違ってたらすみません。

スキルアップ/キャリアアップ(JOB@IT)