質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.59%

ちょっと種類が違うけど結構似てるレコード。ひとつのテーブルに混ぜてもOK?

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,038

score 48

勉強のために、SQLiteで音楽のデータベースを作っています。ふわっとしたお話なのですが…。

songsというテーブルがあり、title、artist、type(楽曲の種類・後述)、length(曲の長さ)、releasedDate(リリース日)、URLといったカラムがあります。
ほかにもいろいろありますがここでは省略します。

そのテーブルに、
type=1:CDの発売をもってリリースとされる楽曲(たとえばAKB48『365日の紙飛行機』)と、
type=2:動画公開をもってリリースとされる、それ以外の楽曲(たとえば黒うさP feat.初音ミク『千本桜』)を
両方入れようと思っています。

type=2のような曲にはURLが存在するので記入します。type=1のような曲には記入しません。

releasedDateには、type=1の場合CDの発売日、type=2の場合動画の公開日などが入ります。

type=1とtype=2を比べて、length(曲の長さ)に違いがあるかなどをのちのち調べるためにデータを作ります。

…といった状況のときに、type=1とtype=2のデータを同じテーブルに入れるのはアリでしょうか?

わたしはべつにいいかなと思っていたんですが、

https://employment.en-japan.com/engineerhub/entry/2018/12/11/110000

ここに、リファクタリングすべきデータベースの例として、

複数の目的に使われるカラム
レコードの属性に合わせて値の意味が変わるカラム
会員だと入会日、スタッフだと入社日とするなど

とあったので、自分の方針はよくないかなぁとも思い相談しました。

この場合、テーブルを分けるのがいいような気もしますが、

「あっやっぱり楽曲ごとに作曲者の情報も載せることにしよう! composerカラムを作るぞ!」

と(あまりよくないですが)なった場合、ふたつのテーブルに対して同じカラムを増やしたものを用意したりするのはよい方法とはいえない気もします。

最終的には自分がどうしたいか?みたいなところに行き着く感じもするのですが、このような状況で、データベース強者はどのような基準で判断して設計していくのかについて、お話を聞かせていただけたらと思います!

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

checkベストアンサー

+1

判断が難しい事柄です。私もさんざん迷いました。

私の考え方を共有します。

マスタ系は、可能な限り正規化すべきです。
トランザクション系は、ある程度許容するが、スーパータイプとサブタイプは分けるべき。

つまり、今回の質問で言うと、マスタ系にあたるので
分けたほうが良いと思います。

私でしたら、このようなマスタにします。
ちなみに、私の提示した楽曲マスタに良くない部分があります。
作詞者と作曲者列があまりよくないです。

■楽曲マスタ

楽曲コード 楽曲名 作詞者 作曲者 CDリリース 動画配信
0001 千本桜 feat.初音ミク 黒うさP 黒うさP

■動画配信マスタ

楽曲コード 配信日 URL
0001 2018/04/29 https://teratail.com/questions/168505

■CDマスタ

楽曲コード リリース日
0001 2018/04/29

考え方としては、動画配信とCDリリースで共通する部分は
楽曲マスタに入っています。
楽曲マスタには、CDリリース、動画配信があるのか表現しています。
動画配信マスタとCDマスタにはそれぞれ、個別の列を定義しています。

メリット
・動画配信、CDリリースの両方に対応する楽曲に対応できる。
・共通項目の変更追加があった時は、楽曲マスタを修正すればよいです。
・各マスタに無駄な列「NULL」ができない
・各マスタの列が最小限になるので見渡しがよくなる

CDリリース、動画配信列は、動画配信マスタにあるかないかで判断できるので
無駄な気もするのですが、楽曲マスタだけですべての情報を見渡せるので、個人的にはこちらが好きです。

デメリット
・テーブルの数が増えるので、JOINが必要になる。
→VIEWで回避可能。
・テーブルの数が増えるので、管理が大変になる
・JOINするのでパフォーマンスに影響がある
→マスタ系だったら、そこまで影響は無いと思うのですが。
リスクはあるということで。

releasedDateに異なる意味の値を入れるのは避けた方が良いと思います。
多少無駄になっても、subscriptionDateとかにしたほうが良いかと思います。
後で誰かが見たときに誤解が生じます。
脳内でtype1だったらこういう意味。と変換する必要も生じます。

もう一つ分ける理由を説明すると、
最初はわずかな違いなので、一つにまとめたテーブルでも
結局後から、どんどん違いが出てきて分けたほうが良かった。ということが結構あります。

なので、基本は分ける。
その後、違いが小さいことが確定したり、パフォーマンスに影響出るようであれば
適宜まとめていく。という考え方がよろしいかと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/01/13 10:34

    ありがとうございます!

    > 作詞者と作曲者列があまりよくないです。

    この2つを外部キーとして、さらに新しいテーブルをつくってそこに黒うさPを格納する、
    というのがさらによい方法ということで合ってますか??

    > CDリリース、動画配信列は、動画配信マスタにあるかないかで判断できるので
    > 無駄な気もするのですが、楽曲マスタだけですべての情報を見渡せるので、個人的にはこちらが好きです。

    わたしも上から順に読んでいったとき、楽曲マスタのテーブルのこの2つのカラムには疑問がありました。
    このふたつはなくしても情報量が損なわれるわけではないですよね?
    また、最初はtype=2だと思っていた(動画配信だけだと思っていた)のに、あとからCDがリリースされた!という場合、
    動画配信マスタのテーブルに1つレコードを追加する必要があるのと同時に、
    楽曲マスタのテーブルの当該楽曲レコードのCDリリースカラムを修正しなければならず、
    もしどちらか片方の修正を忘れてしまった場合にデータが壊れてしまうと理解しています。

    しかし「楽曲マスタだけですべての情報を見渡せる」のはたいへんステキなメリットなので、
    それを天秤にかけてどちらがよいか選択しましょう、ということかと思っています。
    よく本やWebに、正規化が不十分でも運用上の都合を優先することもある、
    と書いてあるのはこのことでしょうか?

    キャンセル

  • 2019/01/14 07:27

    >この2つを外部キーとして、さらに新しいテーブルをつくってそこに黒うさPを格納する、
    >というのがさらによい方法ということで合ってますか??
     はい。そうです。作曲者マスタみたいなものがあるのがベターです。

    >よく本やWebに、正規化が不十分でも運用上の都合を優先することもある、
    >と書いてあるのはこのことでしょうか?
     はい。そうです。ただ、データが壊れる可能性があるなら、カラムは消してしまった方が良いと思ってきました。
     いずれにせよ、まずは正規化ありきで考えて、運用の都合やパフォーマンスを見て
     ベストなテーブル定義を求めていくのが、スマートなやり方だと思っています。

    キャンセル

  • 2019/01/14 11:54

    さらなるお返事ありがとうございました。とてもよくわかりました!
    id:mts10806さんとの会話にも出てきましたが、
    作曲者マスタがあると、同名の人物を区別できるようになりますね。

    やっぱり正規化を優先で考えて、CDリリースと動画配信のカラムはなしでやってみます。
    JOINは苦手だけどがんばろう…!

    キャンセル

+1

DBの寿命はアプリより長い! 長生きするDBに必要な設計とリファクタリングを実践から学ぶ

ご自身で示されている上記リンク先にも書かれていますが、releasedDateデータ情報の何れだと思われますか?

releasedDateには、type=1の場合CDの発売日、type=2の場合動画の公開日などが入ります。

追記

例えば、楽曲に対してCDや動画をメディアとして別なテーブルとして括ると、typereleasedDateを行として管理していても問題はありません。
行として管理するか、列として管理するかというのは、扱うDBMSによって効率の良いアクセスになるかだとかリソースの問題(無駄なカラム)なども絡んできます。

データの持ち方として重要なのは、情報をロストしないこと。
そのためには格納出来ないなどとならない構造である事です。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/01/13 10:04 編集

    情報は効率を考えて必要なら付加するというように考えると良いですね。

    キャンセル

  • 2019/01/13 10:46

    ありがとうございます。

    releasedDateはデータだと思いました! リンク先の例に挙がっている生年月日と同じようなものだから!

    …と思っていたんですが間違いでしょうか?
    せっかく示唆いただいたので考えてみたのですが、よくわかりませんでした……。

    キャンセル

  • 2019/01/13 11:03 編集

    発売日や公開日を読み替えているので編集ですね。
    読み替えている行為があなたによって登録時に行われているので、データだと思うのでしょう。
    typeの判断で発売日や公開日に読み替えできると思うかもしれませんが、同じ楽曲に対して動画もCDある場合、何れかしか格納できないので、レイアウトを変更しないなら、type+楽曲コードをキーにするしかなくなります。

    キャンセル

  • 2019/01/13 11:08

    ありがとうございます!

    id:Kaiserさんにもアドバイスいただいた通り、かりにテーブルひとつでまかなうなら、
    releasedDateのほかにsubscriptionDateというカラムを作らないといけないですね。
    そうするとtypeカラムも必要なくなる…。

    キャンセル

0

テーブルをひとつにまとめるか、複数に分けるかは判断が難しい場合が多いです。どんなSQLが必要か考えてみると良いでしょう。

たとえばSELECTでUNIONまたはUNION ALLを多用しないといけないなら、パフォーマンスが悪いのでひとつのテーブルにまとめるべきだ、って判断します。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/01/13 10:22

    ありがとうございます。たしかにUNIONをそれなりに使うことになる気がします。
    この頻度がどれぐらいなのかによって判断するのは、基準としてわかりやすいです!

    キャンセル

0

「結構似てる」はもはや別のものでは。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/01/13 10:47

    やっぱりそうですかね…テーブル分けるかな…。

    キャンセル

  • 2019/01/13 18:04

    極端な例、同姓同名だけど性別が違うとかそういうのと同じかと。

    キャンセル

  • 2019/01/13 20:06

    さっき設計を考えててその可能性に思い当たり震えあがりました…最初はテーブル1コでいいじゃんと思っていたんですけどどんどん壮大になりますね……。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.59%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る