データベースの正規化について質問です。


行毎にイベントを発生させるXMLを作成したいのですが、行毎の要素の数や内容が異なるので正規化しようと考えています。例えば

記事id,イベントid,タイプ,内容,要素A,要素B,要素C,表示順

がカラムだとします。タイプ毎に内容が変わってしまい、データベースには

1,1,text,テキストが入ります,open,NULL,NULL,1
1,2,img,/image/123.gif,open,big,NULL,2
1,3,bgm,/music/123.mp3,1,pop,id,3
2,4,text,テキストが入ります,close,NULL,NULL,1
2,5,img,/image/456.gif,close,short,NULL,2
.....

みたいなデータが入ります。XMLは記事id毎に取得されて

<text id1="open">テキストが入ります</text>
<img id1="open" id2="big">/image/123.gif</img>
...

と出力されます。このときの正規化はどうしたらよいでしょうか?
タイプ毎にテーブルを作るか、このままでよいのか...
よろしくお願いします。

回答の条件
  • 1人5回まで
  • 13歳以上
  • 登録:2011/09/06 00:40:54
  • 終了:2011/09/09 15:12:37

ベストアンサー

id:language_and_engineering No.2

lang_and_engine回答回数170ベストアンサー獲得回数632011/09/06 10:08:52

アスキーアートのER図で回答します。


もし「イベントタイプごとに,イベントの詳細は3項目以上に増えることは絶対にない」と仕様凍結できるのであれば:


[   記事   ]+-----+∈[イベント]
  ・主キー            ・主キー
                      ・親記事ID
                      ・表示順
                      ・イベントタイプ
                      ・イベント詳細(3列分)


もし「今後,イベントタイプごとに詳細属性の個数は変わりうる。それに,NULLを撲滅したい。完全に正規化したい」のであれば:


[   記事   ]+-----+∈[イベント]+--------+∈[イベント詳細]
  ・主キー            ・主キー            ・親イベントID
                      ・親記事ID          ・詳細項目名
                      ・表示順            ・詳細項目値
                      ・イベントタイプ名


イベントIDが2の「イベント」について考えると

それに属するイベント詳細は2行存在し

「詳細項目名:image_name,詳細項目値:/image/123.gif」

「詳細項目名:open_status,詳細項目値:open」

のようになります。

(3つ目のNULLに対応するレコードを作成する必要は生じません。)

こうすれば,各イベントタイプの仕様を変更しやすくなります。



さらにリレーションを張りたい場合は,

[イベントタイプマスタ] テーブルを作ります。

・主キー

・イベントタイプ名

そして,イベントテーブルにはイベントタイプ名ではなく,

イベントタイプIDを格納します。

そうすれば,「text」を間違えて「txt」にしていた・・・などのタイプミスを防止できます。



反面,このようにテーブルを分割すると

  • 参照時にはJOINの手間が増え,一読して情報の全体像を把握できない
  • 更新処理が複数テーブルにまたがり,更新漏れによる矛盾が起きないようにtriggerなどが必要になる

といったデメリットもあります。


ですので,現状のシンプルな仕様が今後も継続される見込みがあるのであれば,

windofjuly氏のアドバイスに従うのが賢明かもしれません。


参考:

NULL撲滅委員会 - なぜNULLがそんなに悪いのか

http://www.geocities.jp/mickindex/database/db_getout_null.html


外部結合で行列変換 その2(列→行):繰り返し項目を1列にまとめる

https://codezine.jp/article/detail/751?p=2

  • 「列持ち」のテーブルはCOBOLエンジニア等がよく作る泣かせる構造
  • 「行持ち」の構造に変換せよ
id:amichan4

詳しい説明ありがとうございました。

参考になるものばかりでした。

2011/09/09 15:13:30

その他の回答(1件)

id:windofjuly No.1

うぃんど回答回数2625ベストアンサー獲得回数11492011/09/06 09:05:28

私ならば「このまま」にします

 

正規化しておけばデータの意味を読み取りやすくスッキリした印象を受けますが、textやimgといったタイプについては男が1で女が2などと同様に一度決めてしまえば変わることが無い”はず(という前提で話をしています)”ですから、データベースの正規化を行ってJOINによる負荷を増やす必要はなく、単純に属性Bや属性Cがnullであれば無視するというルーチンを組んでおけば良いだけだと思いますので、タイプについては仕様書のほうで対応することとして、私ならば「このまま」にします

id:amichan4

アドバイス通りにさせて頂きます。

ありがとうございました。

2011/09/09 15:14:12
id:language_and_engineering No.2

lang_and_engine回答回数170ベストアンサー獲得回数632011/09/06 10:08:52ここでベストアンサー

アスキーアートのER図で回答します。


もし「イベントタイプごとに,イベントの詳細は3項目以上に増えることは絶対にない」と仕様凍結できるのであれば:


[   記事   ]+-----+∈[イベント]
  ・主キー            ・主キー
                      ・親記事ID
                      ・表示順
                      ・イベントタイプ
                      ・イベント詳細(3列分)


もし「今後,イベントタイプごとに詳細属性の個数は変わりうる。それに,NULLを撲滅したい。完全に正規化したい」のであれば:


[   記事   ]+-----+∈[イベント]+--------+∈[イベント詳細]
  ・主キー            ・主キー            ・親イベントID
                      ・親記事ID          ・詳細項目名
                      ・表示順            ・詳細項目値
                      ・イベントタイプ名


イベントIDが2の「イベント」について考えると

それに属するイベント詳細は2行存在し

「詳細項目名:image_name,詳細項目値:/image/123.gif」

「詳細項目名:open_status,詳細項目値:open」

のようになります。

(3つ目のNULLに対応するレコードを作成する必要は生じません。)

こうすれば,各イベントタイプの仕様を変更しやすくなります。



さらにリレーションを張りたい場合は,

[イベントタイプマスタ] テーブルを作ります。

・主キー

・イベントタイプ名

そして,イベントテーブルにはイベントタイプ名ではなく,

イベントタイプIDを格納します。

そうすれば,「text」を間違えて「txt」にしていた・・・などのタイプミスを防止できます。



反面,このようにテーブルを分割すると

  • 参照時にはJOINの手間が増え,一読して情報の全体像を把握できない
  • 更新処理が複数テーブルにまたがり,更新漏れによる矛盾が起きないようにtriggerなどが必要になる

といったデメリットもあります。


ですので,現状のシンプルな仕様が今後も継続される見込みがあるのであれば,

windofjuly氏のアドバイスに従うのが賢明かもしれません。


参考:

NULL撲滅委員会 - なぜNULLがそんなに悪いのか

http://www.geocities.jp/mickindex/database/db_getout_null.html


外部結合で行列変換 その2(列→行):繰り返し項目を1列にまとめる

https://codezine.jp/article/detail/751?p=2

  • 「列持ち」のテーブルはCOBOLエンジニア等がよく作る泣かせる構造
  • 「行持ち」の構造に変換せよ
id:amichan4

詳しい説明ありがとうございました。

参考になるものばかりでした。

2011/09/09 15:13:30

コメントはまだありません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません