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

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

新規登録して質問してみよう
ただいま回答率
85.50%
データベース設計

データベース設計はデータベースの論理的や物理的な部分を特定する工程です。

Q&A

解決済

2回答

2034閲覧

データベース設計

ikasoumen

総合スコア110

データベース設計

データベース設計はデータベースの論理的や物理的な部分を特定する工程です。

0グッド

0クリップ

投稿2016/08/24 15:30

###前提・実現したいこと
データベースで継承性・共通性を表現したい。

具体的にどういうことかというと、(コードは適当ですが)

humanA .name = "jimmy" .人脈[0] = "father_bob" .人脈[1] = "father_marry" .人脈[2] = "friend_tom" humanB .name = "steve" .人脈[0] = "father_bob" .人脈[1] = "father_marry" .人脈[2] = "friend_john" humanC .name = "tayler" .人脈[0] = "father_bob" .人脈[1] = "father_lily" .人脈[2] = "friend_chris"

A Bを見ると、同じ両親を持っていて、兄弟関係にあります。
Cを見るとbobは再婚し、新たに子を作ったみたいです。

共通性があるのですが、きわめて自由な定義が可能です。

それで、何がしたいかというと、
同じ両親を持ったり、そのオブジェクト個別の値を持ったりということをしたいです。(実際は、人脈パラメータだけでなく、様々なパラメータと値が張ってくる。)

手段として自分が考えているのは、
1.
各オブジェクトに対するパラメータを網羅的に持ち、更新の際に、
パラメータのパターン管理をする属性(たとえば、familiy-A属性や、経歴-○○学校などといったパターン情報)に対して条件判定で更新するなどして、
パターン性を保つ。

2.
オブジェクトに割り当てられたパラメータのパターン(familiy-A属性や、経歴-○○学校など+個別情報)を合成して返す。

1の方が自然かなぁ。

データベースとアプリケーションの設計で定石みたいなのがあったら教えていただきたいです。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

提示されたサンプルからは、
共通性・継承性という点がしっくりきませんでしたが、
上記のような例では関係(リレーション)自体をテーブル化するのがよくあるパターンかなと思います。

###関係のテーブル化
人脈という言葉はいろんな関係性をぼんやりさせてしまうので、
**「両親」とか、「友人」**という関係自体をテーブル化すると、
多少のパフォーマンスは犠牲となりますが、融通が大分利きやすくなります。

更に言うと個人情報みたいなのをマスタテーブル化するとよりすっきりするでしょう。

以下はそれぞれのモデル例です。

個人情報 ID (主キー) 名前 年齢 両親(両親.IDへの外部キー)

SQL

1両親 2 ID(主キー) 3 父親(個人情報.IDへの外部キー) 4 母親(個人情報.IDへの外部キー) 5 一意キー(父親、母親)
友人 個人ID(個人情報.IDへの外部キー) 友人(個人情報.IDへの外部キー) 主キー(個人ID, 友人)

このように分けると、
データベース特有の問題である更新時不整合などの問題も抑制できますので、
そういう意味でも分けると良いかなと思います。
(**「正規化 更新時不整合」**などで調べるとより詳しい情報が得られると思います。)

ちなみに上のようにテーブルを分けた場合、父親が同一の人物を得たい時は、下記のようなクエリで取得できます。

SQL

1SELECT 2 個人情報.* 3FROM 4 個人情報 5 INNER JOIN 両親 6 ON 個人情報.両親 = 両親.ID 7WHERE 8 両親.父親 = 'bob'

###共通性・継承性の表現方法について
一応データベース設計においても、
それらを表現するための技法はあります。

概念データモデリングでよく登場する用語ですが、スーパータイプ、サブタイプというで調べてみると有益な情報が得られるかもしれません。
(基底クラス、派生クラスとかとイメージが近い)

1つ例を挙げますと、
大きく「会員」という括りがあり会員の中でも「一時会員」「特別会員」があるという時。

「会員」がスーパータイプ「一時会員」と「特別会員」をサブタイプとした簡単なテーブル構成を以下に記載します。
(サンプルの構成は単純なのであまり分けるメリット感じられないかもしれませんが)

SQL

1-- 会員タイプ全てに共通する属性はここで定義 2会員 3 会員ID(主キー) 4 会員タイプ -- 「1:一時」「2:特別」 5 会員登録日

SQL

1-- 一時会員固有の属性を定義 2一時会員 3 会員ID(主キー) 4 有効期限

SQL

1-- 特別会員固有の属性を定義 2特別会員 3 会員ID(主キー) 4 付与ポイント残 5 最終ポイント利用日

このようにテーブルを分けることで、
「一時会員」、「特別会員」をテーブル自体で分類して管理できるというメリットがあります。

尚、上記の構成だと共通情報を含んで一時会員を検索する場合は以下のイメージとなります。

SQL

1-- 有効期限切れの一時会員を取得 2SELECT 3 会員.* 4, 一時会員.有効期限 5FROM 6 会員 7 INNER JOIN 一時会員 8 ON 会員.会員ID = 一時会員.会員ID 9 AND 会員.会員タイプ = '1' 10WHERE 11 一時会員.有効期限 < 現在日

###追記
パラメータが動的に変わるという部分を見逃してました^^;

データベースのテーブルでは、
カラム(各種パラメタ値)を動的に増やすのはNGですし、
1つのカラムにはパラメタを連結して登録するのもオススメはできません。
(アンチパターンに記載されるレベルには推奨されてません。)

データベースによってはカラムを配列型として定義できるとものもありますが、
ベンダ依存となるのでこれを利用するのもあまりオススメできません。
なので動的にパラメタが変化する場合は、
パラメタを管理するテーブルを作るのが無難な気がします。
(俗に言う「マルチカラムアトリビュート」対策です)

投稿2016/08/24 17:05

編集2016/08/24 23:44
Panzer_vor

総合スコア1636

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ikasoumen

2016/08/31 02:41

データベースにも、スーパータイプ、サブタイプというオブジェクト指向的な思想がデータベースにもあるのですね。 今回のアプリケーションで使えそうな部分があるので参考にさせていただきます! 設計で一番問題にしているのは、 データベースの設計をユーザを行うことです。 その背景には値を一元管理し整合性を保担保と動的な値変更をサポートするために、 エクセルで管理していたデータをデータベースに移行するのですが、 それは業務アプリケーション作成のためでなく、 あるプロジェクトで利用するパラメータの管理を行うためです。 期間的に、プロジェクトの全貌が見えてきてから、 テーブル設計を行うのでは時間が足りないので、 ユーザがある程度設計を行いそのままテーブル構造にしてしまうことを想定しています。 そのため汎用的な仕組みを用意しておきたいという狙いがあります。 うーん、自分で書いてて炎上必須な気がしてますが、 データベースの設計について勉強しようと思います。
Panzer_vor

2016/08/31 03:32

> ikasoumenさん 一時的に各種パラメータ値を管理したいという要件でしたら、パラメタ管理用の汎用区分のマスタと汎用テーブルをこしらえれば良さそうですね。 汎用区分マスタのカラムとしては「区分ID」、「区分名」あたりを用意。 汎用テーブルのカラムとしては、「区分ID」、「パラメタID」、「パラメタ名」あたりを用意。 それでもって区分IDでリレーションを張り、汎用テーブル側には外部キーを定義すれば整合性は保てますし。 データのイメージは以下のような感じになります。 マスタ側 区分ID、 区分名 1 、 家族 汎用テーブル側 区分ID、パラメタID、パラメタ名 1、 1、父親 1、 2、母親
ikasoumen

2016/08/31 04:02

ありがとうございます。 値はどこで持つのがいいのでしょうか? 家族A、家族Bがあり、互いに同じ父を持つ場合、 その父の名前を変更したとき、家族A、家族Bの父は同一の名前でなければいけません。
Panzer_vor

2016/08/31 13:03

> ikasoumenさん 値を保持させるなら汎用テーブル側になると思います。 上記で例示したものはカラムとして最低限しか用意してませんが、 例えば汎用テーブル側に「汎用1」みたいなカラムを用意し、 そこに必要に応じて別のパラメタIDを保存するなどすると、 パラメタ間で関連を持たせることも可能です。 マスタ側 区分ID、 区分名 1 、 家族 2 、 人物名 汎用テーブル側 区分ID、パラメタID、パラメタ名、汎用1 1、 1、家族A、1 1、 2、家族B、1 2、 1、bob 2、 2、john 上記の例では、 汎用1に保存したIDは区分「人物名」のID=1(bob)を保存しています。 この場合区分IDは利用者側が知っていなければなりませんが、 それが気にいらない場合は、 汎用テーブル側で各レコードで一意となるID列を導出する手もあるかなと。 ただ汎用的にしすぎると、 その分保守が困難になるので要注意ですが。
ikasoumen

2016/09/07 15:40

ありがとうございます。 汎用性とメンテナンス性のバランスを取りながら 仕様を考えたいと思います。
guest

0

ご質問の意図を汲み取り切れているか不安ですが、
・データベースを粒粒で構築
・アプリは粒粒のデータベースから値を取得してオブジェクトを作る
といった感じではないでしょうか?

● テーブル名称(カラム名称, ...) : (カラム値, ...) ...

Humans(name): (jimmy), (steve), (tyler)
Fathers(name, fatherName): (jimmy, bob), (steve, bob), (tayler, bob)
Mothers(name, motherName): (jimmy, marry), (steve, marry), (tayer, lily)
Friends(name, friendName): (jimmy, tom), (steve, john), (tyler, chris)

● 例示されたオブジェクトの作成(ビューでも良いかもです)

select h.name, fatherName, motherName, friendName from Humans h, Fathers f, Mothers m, Friends fr where h.name=f.name and h.name=m.name and h.name=fr.name

属性を追加したいのであれば、追加された属性のテーブルを追加し、SQLを修正で対応できると思います。
(学校の追加ならSchoolsテーブルを作成 など)

投稿2016/08/24 16:52

snowfaller

総合スコア125

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ikasoumen

2016/08/31 02:54

ありがとうございます。 参考にさせていただきます! 粒粒は、データベースを分けたり、テーブルを分けたりしようと思っています。 そうしないと、一元性を担保できないと思っているからです。 共同開発者と認識が合致しておらず、 一人は、エンティティアトリビュートヴァリュー設計にしようとしていたり、 一人は、パラメータを全部列にしようとしていたりします。 私はパラメータを行に持つようにするとして、 管理したい単位でデータベースとテーブルを分けるようにしたいと思っています。 何がまずいかっていうと、誰もまだ確度を保証できてないところです。 自分一人で意思決定が進むならまだ楽ですが、 仕事の難しさを実感しています。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問