QA@IT
«回答へ戻る

回答を投稿

実際のデータはわかりませんのでそれを抜きにして提示された情報で感じた印象ですが、
game_informationsテーブルの役割がよくわかりません。

gamesにはゲーム固有の情報の一部(メーカーやジャンルにまつわる情報以外)が入るのでしょうか。gamesのidは、game_informationsのgame_idと紐づくわけですね。

game_informationsはgame_idを持たないといけないので、仮に同ジャンルを同じメーカーから発売していてもgame_idの数より少なくなることはできません。これはこのテーブルがあくまでゲーム固有の情報の一部を垂直分割しただけのテーブルなのでいいということなのでしょう。

そしてgame_information_makersはgame_information_idを持つのでgame_information_idより少なくなることはできません。つまりはgamesと少なくとも同じ件数になるわけですね、分割前を考えれば同じ件数ということでしょうか。

ということは、game_information_makers.idとはgames.idの別称ともいえるわけでgame_information_idではなくgames_idを持っても同じことになるような気がします。
game_informationsにどういう情報を持たせるのかにもよってくるのですが

  1. game_informationsにはgamesとそれ以外のテーブルを紐づけるためのキー情報しか持たない
    この場合はテーブルが増えるだけでgame_informationsは分割に寄与していません。
    なぜなら、game_informations.idとgame_informations.game_idが同じ値でも成り立ってしまうからです。

  2. game_informationsはキー以外に実データも含む
    この場合を突き詰めていくとgamesテーブルはidだけでよくなります。idしか持たないテーブルが有用かどうかは説明するまでもないと思います。

なので、gamesとgame_informationsのいずれかは不要な表ではないかと感じました。

ここで、3番目の画像を見てみると、gamesはジャンルとメーカーを持っていますね、これはジャンルとメーカーのキーを持っていてそれをつかってジャンルやメーカーの情報を取得しにいく単純な正規化の話でしょう。そしてジャンルやメーカーはゲームのidに紐づく情報を持っていません。

もう一度 2番目の画像を見てみるとジャンルやメーカーがゲームに紐づくための情報を持っていることがわかります。

3番目の画像で

games --> game_information_makers

という探索方向だったものが2番目の画像では

games <-- game_informations  <-- game_information_makers

という探索方向に変わっているということです。。

新規に設計した場合ならば、メーカーよりもゲームの方が多いと思いますので、主キーが重複してしまうことになるでしょう。
と、いうことで2番目の設計はよくないと思います。

たぶん、

<初期状態>
Table: games 
  Fields: game-id,   name, release-date, 
          maker-name, maker-country,
          genre-name, genre-kana

<正規化する>
Table: games 
  Fields: game-id, name, release-date, 
          maker-id, genre-id

Table: makers 
  Fields: maker-id, maker-name, maker-country

Table: genres
  Fields: genre-id, genre-name, genre-kana

※ この例では列数が少ないからわからないが、元の列の数が何十倍にもなると
   この段階ではgamesがidだらけでgameの情報を探すのが大変だったり
   idなんだか日付なんだかもパッと見でわからない状態で不満が残ったとする。

<中間テーブル作る>
Table: games 
  Fields: game-id, name, release-date

Table: games-ext-info
  Fields: game-id, maker-id, genre-id

Table: makers 
  Fields: maker-id, maker-name, maker-country

Table: genres
  Fields: genre-id, genre-name, genre-kana

というのと、

<初期状態>
Table: games 
  Fields: game-id,   name, release-date, 
          maker-name, maker-country,
          genre-name, genre-kana

<垂直分割する>
Table: games 
  Fields: game-id, name, release-date

Table: games-makerpart
  Fields: game-id, maker-name, maker-country

Table: games-genrepart
  Fields: game-id, genre-name, genre-kana

(makerやgenreが正規化できたとして、中間テーブル作るとさっきと同じものができると思います)

がごっちゃになったんじゃないでしょうか。

前置き(というか重箱の隅というのか)がだいぶ長くなってしまったんですが、
現状で分割することばかりに意識がとられていて概念設計(データベースを抜きにして、データにはどういう実体が存在しているのか、どういう関連なのかの整理)や論理設計が不十分な状態で物理設計にはいっているような印象があります。(やっていたらごめんなさい)

この手の状況はメインフレームのデータをRDBに落とし込むときによく見かける気がしますが、この手のデータで気になるのはデータの質といいますか正規化が可能な状態にあるかですね。

たとえばユーザーの住所情報で言えば、郵便番号がキーとなりえて、都道府県、市区町村が選択された値が基本であれば、ユーザーによるばらつきがない個所はマスタデータなどに分離して一部のデータはキーで管理することができます。
しかし郵便番号、都道府県、市区町村の項目はわかれてはいるが入力者が思うがままに入力可能だったり、「xx年より前はカナしかなくxx年より後は漢字しかない(そして古いデータのメンテもされない)」といったばらつきがあれば同じ件数のテーブルに分ける(垂直に分割する)しかできません。この場合は中間テーブルを作ったところで基本的に分割前のキーを複数持つだけなのでその意味合いは薄くなるように思います。

複数の1対1の関係を1つの中間テーブルに閉じ込める場合(私が書いたTable: games-ext-infoの様な状態)ですが、仮に 1つのゲームを複数の会社が共同で作るから複数登録したいと言われた場合にどうするかですね。
「構成の変更がしやすい」には反するかと思います。
一部の情報だけ選択したい場合に不要なキー情報がたくさんついてくるのも気になりますね。中間テーブルがシンプルでない(複数の関係情報を持つ)のでActiveRecord(パターン?Rubyの方?)に頼った場合はコストが心配になります。
すべてのケースに対応するのは不可能ですし、仮定の話ですが様々なことを予想しておくのは大事だと思います(実装に盛り込む必要はないですが)。

「情報が視覚的に分かりやすくなる」は「誰」が「どんなときに」分かりやすいのかまで考えるといいと思います。

求めていた回答とはちがうかもしれませんが長々と失礼しました。

実際のデータはわかりませんのでそれを抜きにして提示された情報で感じた印象ですが、
game_informationsテーブルの役割がよくわかりません。

gamesにはゲーム固有の情報の一部(メーカーやジャンルにまつわる情報以外)が入るのでしょうか。gamesのidは、game_informationsのgame_idと紐づくわけですね。

game_informationsはgame_idを持たないといけないので、仮に同ジャンルを同じメーカーから発売していてもgame_idの数より少なくなることはできません。これはこのテーブルがあくまでゲーム固有の情報の一部を垂直分割しただけのテーブルなのでいいということなのでしょう。

そしてgame_information_makersはgame_information_idを持つのでgame_information_idより少なくなることはできません。つまりはgamesと少なくとも同じ件数になるわけですね、分割前を考えれば同じ件数ということでしょうか。

ということは、game_information_makers.idとはgames.idの別称ともいえるわけでgame_information_idではなくgames_idを持っても同じことになるような気がします。
game_informationsにどういう情報を持たせるのかにもよってくるのですが

1. game_informationsにはgamesとそれ以外のテーブルを紐づけるためのキー情報しか持たない
この場合はテーブルが増えるだけでgame_informationsは分割に寄与していません。
なぜなら、game_informations.idとgame_informations.game_idが同じ値でも成り立ってしまうからです。

2. game_informationsはキー以外に実データも含む
この場合を突き詰めていくとgamesテーブルはidだけでよくなります。idしか持たないテーブルが有用かどうかは説明するまでもないと思います。

なので、gamesとgame_informationsのいずれかは不要な表ではないかと感じました。

ここで、3番目の画像を見てみると、gamesはジャンルとメーカーを持っていますね、これはジャンルとメーカーのキーを持っていてそれをつかってジャンルやメーカーの情報を取得しにいく単純な正規化の話でしょう。そしてジャンルやメーカーはゲームのidに紐づく情報を持っていません。

もう一度 2番目の画像を見てみるとジャンルやメーカーがゲームに紐づくための情報を持っていることがわかります。

3番目の画像で
```
games --> game_information_makers
```
という探索方向だったものが2番目の画像では
```
games <-- game_informations  <-- game_information_makers
```
という探索方向に変わっているということです。。

新規に設計した場合ならば、メーカーよりもゲームの方が多いと思いますので、主キーが重複してしまうことになるでしょう。
と、いうことで2番目の設計はよくないと思います。


たぶん、
```
<初期状態>
Table: games 
  Fields: game-id,   name, release-date, 
          maker-name, maker-country,
          genre-name, genre-kana

<正規化する>
Table: games 
  Fields: game-id, name, release-date, 
          maker-id, genre-id

Table: makers 
  Fields: maker-id, maker-name, maker-country

Table: genres
  Fields: genre-id, genre-name, genre-kana

※ この例では列数が少ないからわからないが、元の列の数が何十倍にもなると
   この段階ではgamesがidだらけでgameの情報を探すのが大変だったり
   idなんだか日付なんだかもパッと見でわからない状態で不満が残ったとする。

<中間テーブル作る>
Table: games 
  Fields: game-id, name, release-date
          
Table: games-ext-info
  Fields: game-id, maker-id, genre-id

Table: makers 
  Fields: maker-id, maker-name, maker-country

Table: genres
  Fields: genre-id, genre-name, genre-kana
```
というのと、

```
<初期状態>
Table: games 
  Fields: game-id,   name, release-date, 
          maker-name, maker-country,
          genre-name, genre-kana

<垂直分割する>
Table: games 
  Fields: game-id, name, release-date

Table: games-makerpart
  Fields: game-id, maker-name, maker-country

Table: games-genrepart
  Fields: game-id, genre-name, genre-kana

(makerやgenreが正規化できたとして、中間テーブル作るとさっきと同じものができると思います)
```
がごっちゃになったんじゃないでしょうか。


前置き(というか重箱の隅というのか)がだいぶ長くなってしまったんですが、
現状で分割することばかりに意識がとられていて概念設計(データベースを抜きにして、データにはどういう実体が存在しているのか、どういう関連なのかの整理)や論理設計が不十分な状態で物理設計にはいっているような印象があります。(やっていたらごめんなさい)

この手の状況はメインフレームのデータをRDBに落とし込むときによく見かける気がしますが、この手のデータで気になるのはデータの質といいますか正規化が可能な状態にあるかですね。

たとえばユーザーの住所情報で言えば、郵便番号がキーとなりえて、都道府県、市区町村が選択された値が基本であれば、ユーザーによるばらつきがない個所はマスタデータなどに分離して一部のデータはキーで管理することができます。
しかし郵便番号、都道府県、市区町村の項目はわかれてはいるが入力者が思うがままに入力可能だったり、「xx年より前はカナしかなくxx年より後は漢字しかない(そして古いデータのメンテもされない)」といったばらつきがあれば同じ件数のテーブルに分ける(垂直に分割する)しかできません。この場合は中間テーブルを作ったところで基本的に分割前のキーを複数持つだけなのでその意味合いは薄くなるように思います。

複数の1対1の関係を1つの中間テーブルに閉じ込める場合(私が書いた`Table: games-ext-info`の様な状態)ですが、仮に 1つのゲームを複数の会社が共同で作るから複数登録したいと言われた場合にどうするかですね。
「構成の変更がしやすい」には反するかと思います。
一部の情報だけ選択したい場合に不要なキー情報がたくさんついてくるのも気になりますね。中間テーブルがシンプルでない(複数の関係情報を持つ)のでActiveRecord(パターン?Rubyの方?)に頼った場合はコストが心配になります。
すべてのケースに対応するのは不可能ですし、仮定の話ですが様々なことを予想しておくのは大事だと思います(実装に盛り込む必要はないですが)。

「情報が視覚的に分かりやすくなる」は「誰」が「どんなときに」分かりやすいのかまで考えるといいと思います。

求めていた回答とはちがうかもしれませんが長々と失礼しました。