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

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

ただいまの
回答率

90.47%

  • MySQL

    6019questions

    MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

  • PostgreSQL

    1100questions

    PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

RDB で テーブルを分割するか NULL を許容するか

受付中

回答 9

投稿

  • 評価
  • クリップ 1
  • VIEW 211

overdist

score 2

 テーブルを分割するか NULL を許容するか

MySQL などの RDB の設計で悩んでいます。

NULL は排除できるなら極力排除するべきだという教えが一般的だと思うのですが、許容しても良い判断基準をどのように持てば良いのかが、自分の中でわかっていません。

例えば、ユーザテーブルがあり、結婚した日というカラムがあったとします。ユーザには結婚した人もいれば、していない人もいます。このとき、結婚日を NULL 許可するのか、結婚日テーブルのように分割するのか…。

使い方としては、全ユーザ一覧の中で結婚した人の絞り込み・結婚していない人の絞り込み・今年結婚した人の絞り込みなどの用途があります。つまり、テーブルを分割したとしても結局多く使わる SQL では LEFT OUTER JOIN をすることになるので NULL が入ってくることになります。

これが詳細プロフィールのように任意のデータが複数あるような集合だった場合は別テーブルに分割するという感覚はあるのですが、それが1列の場合はどうなのか。その NULL を含めた列を WHERE などの条件として使うような用途の場合はどうなんだろう…と色々な条件で考えていくとキリがなく。

おそらく色々なケースによって判断されると思うので一概にこっちだとは言えないと考えているのですが、みなさんの判断基準を参考にさせてもらえると助かります。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 9

+3

NULL は排除できるなら極力排除するべきだという教えが一般的だと思うのですが

最近データベースは触ってないので最近の一般論はわからないですが、少なくとも私の中にはそのような考えはないです。
NULL(値がない)という情報が必要なシーンは多数ありますから、状況に応じて使い分ければよいと思います。

で、今回の「結婚日」で言えばNULLを許可でよいと思います。
結婚に付随する情報が多数ある場合、例えば、配偶者の情報や過去の婚姻暦などが必要であれば、結婚テーブルを用意するとよいと思います。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

+2

結婚した日は個人に属する情報ですから、通常はユーザーテーブルに含めるでしょう。

結婚相談所のシステムなら何度も結婚・離婚しているような相手は避けたいって要望があるから、結婚・離婚の履歴を別テーブルで用意するでしょう。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

+2

項目がNullを取りうるかどうかがテーブルを分割する条件とは成り得ません。

また、Nullを排除する必要があるのは必須であるかどうかです。

Nullはインデックスに含まれませんから、
Nullとなる項目に対して、Null値が検索対象となる場合は、
Nullに特定の値を与える事で、インデックスの効果を得る事ができます。

このような事に対して、「NULL は排除できるなら極力排除するべき」という結果だけが浸透してしまったのではないでしょうか。
※逆にNULL値が検索対象から除外が前提なら、Nullのままとした方が、インデックスの件数が少なくなる分効率的です。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

+2

RDB はその概念設計の時点から、NULL を特別な値として扱うことを前提として構築されています。
※true/false の二値論理ではなく true/false/null の三値論理であることとか

ですからデータの構成上 NULL はあってはならないなら排除するのはいいのですが、逆に構成上 NULL があってよいならば、それは正しく NULL を扱うべきだと思います。

今回の例でいえば、未婚の場合は当然結婚日が存在しないのですから、null を許容すべきだと思います。
※欧

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

+1

例えば、ユーザテーブルがあり、結婚した日というカラムがあったとします。ユーザには結婚した人もいれば、していない人もいます。このとき、結婚日を NULL 許可するのか、結婚日テーブルのように分割するのか…。 

これくらいであれば分割する必要はないかと思います。
例えば「結婚記念日テーブル」を別で持ってユーザーIDと紐づけたとしても、検索の際には仰っているようにJOINする必要がありますし。

検索の要件次第でもありますね。
結婚記念日だけを検索する機能があるのでしたら分割するメリットはあるかもしれません。
でもその機能に「未婚」というのがあるのでしたら分割するメリットはなくなります。

テーブルを分割するのでしたら子テーブルに複数行入ることが想定されるケースが多く当てはまるのではないかなと。
teratailの質問に対する回答やコメントなんかはまさにそれですね。

もちろん1行しかなくても分割するメリットがないわけではないかなと思います。
すごく項目数が多いとか。
実際は名前しか表示されない、検索も名前のみ検索しかしないのに、明細情報まで引っ張ってくる必要はありませんよね。
SNSにおける詳細プロフィールなんかがそれにあたるでしょうか。
明細にしか表示しないようであれば、検索に必要な項目のみ親として、子に明細情報を持っておくというのもあります。

ある程度理解はされているように見受けられますが、「検索条件に利用するかどうか」で決めてはいかがでしょうか。
もちろん「将来的に検索項目が増えるかもしれない」のであれば分割せずに突っ込んでおいても良いですし。
レコード数が多くなると当然分割したテーブルとJOINするのも結構負荷が高いですから、「将来的な観測」は幅広めに持っておいて良いかなと思います。
拡張性の観点からすると難しいところはあるかもしれませんが、そこは設計時にどこまで見越すかということになりますので、DBだけの問題ではないので、
実際の要件・設計と相談して決めてください。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

+1

NULL は排除できるなら極力排除するべきだという教えが一般的だと思うのですが

一部に「テーブルを分割してでもNULLは入れるべきでない」という過激派がいますが、そうではなくて「排除できるなら」がNULLが来るのが正当ではない(たとえば、電話帳での名前や電話番号の列など)なら、というもう少しゆるい意味で捉えている可能性も考えられます。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

+1

NULL排除の観点ではないですが、結婚日を複数保持する必要があるかどうかでテーブルを分割するかどうかを考える必要もあるのではないでしょうか。
直近の結婚日1件だけ保持したいならテーブルを分割するまでもないと思いますが、過去の結婚日の履歴が全て必要ならテーブル分割すべきかと思います。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

+1

 NULLを排除すべき具体例

趣味のように複数選択ができて、不特定多数のものなどについて

人名 趣味
Aさん 読書,映画鑑賞
Bさん 映画鑑賞,野球
Cさん 釣り
Dさん なし

上記をまともにテーブルで管理すると

人名 趣味・読書 趣味・映画鑑賞 趣味・野球 趣味・釣り
Aさん 1 1 NULL NULL
Bさん NULL 1 1 NULL
Cさん NULL NULL NULL 1
Dさん NULL NULL NULL NULL

こうなって、これではあまりに無駄が多いです(横に無限に広がっていく)

人名 趣味1 趣味2 趣味3 趣味4
Aさん 読書 映画鑑賞 NULL NULL
Bさん 映画鑑賞 野球 NULL NULL
Cさん 釣り NULL NULL NULL
Dさん NULL NULL NULL NULL

多少効率化をはかってこうしてみても趣味1~4が違う集計項目になるし
一人あたりの趣味の上限が決まってしまうのも具合が悪いでしょう。

これを解消するには

  • personテーブル
pid 人名
1001 Aさん
1002 Bさん
1003 Cさん
1004 Dさん
  • hobbyテーブル
hid 人名
2001 読書
2002 映画鑑賞
2003 野球
2004 釣り

※idを見やすくするため便宜上1000、2000番台をつかっています

というマスター管理をして

  • person_hobbyテーブル
phid pid hid
1 1001 2001
2 1001 2002
3 1002 2002
4 1003 2004

中間テーブルをつかって管理するのです

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/11/09 14:48

    あともう一点
    「結婚した日」は必ずしも1人あたり1日ではないこと。
    離婚したら結婚した日の情報を消すのか?
    消さないなら再婚したときに2つもつのか?
    など仕様がかたまってないとテーブルの設計はできません

    キャンセル

0

的外れかもしれませんが、親レコードとの関係が 1:n である可能性はご考慮の上でしょうか。
すなわち、ご質問の例で言えば人は2回以上結婚することがありえます。

結婚した日というのが【現在婚姻中の場合はその成立日、そうでなければnull】という定義ならnullableカラムで十分です。
【結婚経験があるならその成立日】だったら 1:n ですから別テーブルにせざるを得ません。

「結婚した日」というのがお仕事で本当に扱っている要件でなくて質問のための仮の要件だとしても、似たような構造がありえるので仕様を一度洗い直しておく必要性を感じました。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

関連した質問

  • 解決済

    facebookの友達機能のようなものを作りたい

    facebookの友達機能のようなものをphpとmysqlで作りたのですが、 なにをどうすればいいのかわからないので、教えてください。 流れは AさんがBさんに友達申請をする。

  • 解決済

    Webアプリケーションの不確定データのDB格納

    現在、ユーザー登録をしてログインして利用する Webアプリケーションを開発しています。 言語はPHPです。 ユーザー登録時にメールアドレス(ログインID)と パスワード以外に年

  • 解決済

    VBA

    お尋ねします。 ACCESSで商品テーブルのフィールドで IIf([テーブル1]![フィールド1]=[テーブル2]![フィールド1],True,False) IIf([テーブ

  • 解決済

    【MySQL】顧客データを「家族」としてまとめる為のテーブル設計

    テーブル設計について悩んでおります。 お知恵をお借りできたらと思い投稿しました。 乱筆の上長文となりますが よろしくお願いします。 現在、顧客データを管理するテーブ

  • 解決済

    外部キーがnullであることによる問題点

    現在構築しているシステムについて 採用管理システムを構築しており、以下のようなデータベース構造を検討していました。 応募者テーブル [ID][応募日][名前][連絡

  • 解決済

    DBの行と列でのデータの持ち方

    グループ3社で対象になるユーザがどの会社の権限許可があるかの設定を設けようと思っているのですが、会社ごとの許可フラグをカラムとして列で持つか、 それともカラムを会社IDとし、レコ

  • 解決済

    FileMakerで複数の階層のテーブル構築について

    前提・実現したいこと 初めまして、reyjdと申します。 いつも参考にさせていただいております。 今回はFilemakerで目標~タスク管理のデータベースの構築を 行っている途

  • 受付中

    【CakePHP3】バリデーションで複合カラムのユニーク制約をしたい

    課題 新規登録時に email と hoge_id の複数のカラムでユニークにしたいのですが、 調べてもなかなか出てこず、ハマりました(汗) ソースコード public

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

  • MySQL

    6019questions

    MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

  • PostgreSQL

    1100questions

    PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。