[チャット研修]RDBのリレーションについて(1:多から多:多への物語~)

 

2022年09月04日

[チャット研修]RDBのリレーションについて(1:多から多:多への物語~)






サポーターを担当しているぽんです。
研修?の内容を書き起こしました。

9月に新しいメンバーが入社しました。嬉しい限りです。
エンジニアの才能を活かすも殺すも”環境”だと思います。

初場所の環境が本当に重要です。

入社して頂いたからには、”1から構築する能力”を身に付けて、自分が作りたいサービスを作れるエンジニアになっていただきたいです。

プログラミング力=データ処理能力は、独学でもいけると思います。しかし、DB設計やネットワークの知識はある程度伝えて全体感を理解してもらうほうが良いと思っています。

研修はチャットベースです。チャットで伝えるのが1番理解力が深まると思ってます。

今回は、DBのリレーションについて伝え、携わるプロジェクトが“なぜ、このようなテーブル設計なのか”を理解してもらうことをゴールとしています。

この記事について

RDBのリレーションを理解するスレ

1:1と1:多の関係を把握してほしいです♪
多:多は無視!
下記の場合、どちらかを答えてください!
正解はないのでご自由に♪
・株式会社うちなーてっくに従業員が複数人所属している
(条件 従業員は1つの会社しか所属できない)

ありがとうございます!
この場合、1:1かと思うのですがどーでしょうか??

ファイナルアンサー?

会社と従業員の関係です!

イメージですが
社員ID | 名前
1 | 山田
2 | 森
3 | 佐藤
のようなテーブルがあった場合、これは1:1でしょうか??

社員と名前は1体1ですね!社員1人につき名前は1つ

会社1に対して従業員は?

なるほど!!
とすると、1つのうちなーてっくという会社に社員が複数人ということは1:多が正しいという認識であっていますでしょうか??

正解!!
次の質問へ進みますか!?

なので、抽象化すると、
会社1つに対して従業員は複数人所属できます
ここまでOK牧場ですか?!

OK牧場です!!

はい!
プライマリキーという単語はご存知です?

IDなどの重複しない一意の値と言う認識をしています。

そうですね!
Rdbテーブルで必ず存在するキーで、レコードを識別します

Rdbとはなんのことでしょうか??

リレーショナルデータベースのことです!MYSQLとかポスグレスとかです

リレーショナルの意味が理解できていませんでした。表形式のDBを連結したりできるDBのことを指す認識で大丈夫でしょうか??

データの関係性を保持したまま保管できる仕組みですね!まぁ、そういうもんなんだって思ってください!

了解です!

会社テーブルと従業員テーブルを作成するとします。
会社テーブル => companys
従業員テーブル => staffs
テーブルは意味のまとまりごとにつくるイメージです
適当なこと言ってるかもしれませんが、詳しくは書籍でw
ここまでOKでしょうか?

OKです!!


ではでは、
companysテーブルに属性を追加しましょう!
クライアントの要件は、会社名と住所がほしいとのことです。


イメージできてます。


では属性を追加します。
idをプライマリキーとしましょう!なので
id
name
address


では、データを挿入します
id, name, address
1, うちなーてっく, 沖縄
2, Google, 宮古島
3, Facebook, 津堅島


非常にわかりやすいです!www

わたし、プログラミング講師めざしてるので!!w
では、staffsテーブルにも属性を追加しましょう!
クライアントの要件は、名前と生年月日がほしいとのことです。
では属性を追加します。
companysと同じく、idをプライマリキーとしましょう!なので
id
name
brith_day
OK?

OKです!!


でですね!
staffsは、1つの会社に所属するんです!!
必ず、会社に所属しています。
ニートはいないんですね。
OKです?


OKです!!

では、従業員を会社に“紐付け“ましょう!!
staffsテーブルにカラムを追加します
company_id
この“紐づけること” => “関係性“を持たせることをリレーションといいます

はい!

では質問です。
company_idカラムには、companysテーブルのどの値を挿入すればよいか
id
name
address
どれでしょう〜 (


IDだと思います!

それど質問なのですが、このカラムを作成すると言う事は3つ目のテーブルが作成されると言う認識で大丈夫ですか?


>IDだと思います!
正解!
>このカラムを作成すると言う事は3つ目のテーブルが作成されると言う認識で大丈夫ですか?
違います!
staffsテーブルにcompany_idカラムを追加します。

ありがとうございます!
大丈夫です!


テーブルは1つの意味のまとまりなので、従業員に関することは従業員テーブルにまとめます。


了解しました。

結果として、staffsテーブルは下記になります
id
company_id
name
birth_day
OK?

OKです!

データを挿入しましょう!
id, company_id, name, birth_day
1, 1, A氏, 19900901
2, 1, B氏, 1500505,
3, 3, 友田, 19950501

質問です!
B氏と友田の所属会社は?

B氏がうちなーてっく
友田がFacebook
だと思います!


正解!!


Facebookが社名をMetaに変更しました!
そうすると、変更箇所はcompanysテーブルのnameの箇所のみです。
staffsテーブルを変更する必要はありません。
会社に関することは会社のテーブルで完結できます


なるほど!
便利だと思います!!


そうです!!
この関連したテーブルを設定するカラムを“外部キー“と呼びます。
今回のように、companysのプライマリキーをstaffsテーブル設定します


理解できました!


例えばですね〜、
Facebook社が1億人いたとしましょう
そして、staffsテーブルにはcompanysテーブルのキーではなく
単に社名を属性とします。
id, company_name, name, birth_day
1, うちなーてっく, A氏, 19900901
2, うちなーてっく, B氏, 1500505,
3, Facebook, 友田, 19950501
,
,
,
,
1億人
この場合、Facebook->Metaに社名変更するだけで、1億人のstaffsレコードを更新しないといけません。
さらに、更新の途中で更新ミスが発生したとしましょう。
Facebookのままの人もいるのです!!
これはいけないですよね!?
いわゆる“整合性“が保てていません!
検索していくうちにRDBは、“整合性が〜“とか文章みると思いますが、こういうことです。

staffsに外部キーを設定することで“整合性を保証“しています
ここまでOK?
重要キーワード
・プライマリキー
・外部キー
・整合性
・友田の解説わかりやすい


はい!
大丈夫です!
理解出来ています!


いいですね!!
1:多の関係とは、このように会社と従業員の関係を指します。
さ〜てここからが本番です!
クライアントから“従業員は複数の会社に所属できるようにしほしい“と言われました!

1日前
これ以降は、有料会員になります
ご指定の口座に振り込んだ方のみ進めます

冗談ですよ!


www
続きをお願いします!笑

お〜〜!!
udemy用につくろっかなw
では、A氏さん考えてください!
このクライアントの要望に対してどう設計しますか?
従業員は複数の会社に所属できる


正解はないです


staffsテーブルにカラムを追加して対応するって思い浮かびません?


変更を加えるならstaffsテーブルかなと直感的に思いましたがどう言ったカラムを追加するのかがイメージできませんでした。
一つのカラムに複数のIDを入れることは出来ますか?


良き着眼点です!!!
一つのカラムに複数のIDを入れることは出来ますか?
NGです!
外部キーは1つです
staffsテーブルに下記カラムを追加したらいけると思いませんか?
companysへの外部キーカラムを複数作成する
company_1_id
company_2_id
company_3_id


そうすると、友田がうちなーてっくとGoogleにも所属した場合
※プライマリキーをpkに略します
id 3
company_1_id 1 <-うちなてーくのpk
company_2_id 2 <-Googleのpk
company_3_id 3 <-Facebookのpk
name 友田
birth_day 19950501


こうすれば、友田は3つの会社に所属でき、
例えば100個の会社ができても100カラム追加すれば対応できます。


なるほど!!
一つのカラムに複数ではなく複数のカラムを作成すればいいんだ!!
理解できました!

お〜!素晴らしいです!!
これで、クライアントの要件を満たせますよね!


だが!!!!


だが!!??


これじゃ、ダメなんですよ!
これって、1人の所属会社が増えるたびにカラムを追加しないといけないですよね?
友田は優秀なので、毎日所属会社が増えます。
そうなると、毎日カラムを追加して、とんでもない量のカラムになります
company_1_id
company_2_id
company_3_id
,
,
,
,
company_500_id


たしかに。。


かたやB氏はずっと1つの会社です
company_1_id以外のカラムは値が入りません。。
全てNULLです。。。。

なるほど。。。


そうです。。
ここで、クライアントの要件が追加されたことによって
会社と従業員の“関係性“をあらためて考えてみましょう!


はい。

変更前
会社1つに対して複数の従業員
従業員1人にたいして会社は1つ
従業員は、1つの会社に所属する => 1
会社は、複数の従業員を所有する => 多
なので“1対多“でしたね?


はい!


変更後
従業員は、複数の会社に所属する => “多”
会社は、複数の従業員を所有する => 多

1:多

多:多
の関係になりました!


なるほど。
多:多の関係に。


今まで、1つの会社にしか所属できなかった従業員が複数の会社に所属できるようになったのです!!


で、は

これを解消する方法を考えましょうか
↓↓
これじゃ、ダメなんですよ!
これって、1人の所属会社が増えるたびにカラムを追加しないといけないですよね?
友田は優秀なので、毎日所属会社が増えます。
そうなると、毎日カラムを追加して、とんでもない量のカラムになります
company_1_id
company_2_id
company_3_id
,
,
,
,
company_500_id


OK?


はい。


ここで、テーブルを一つ追加するんです!
companysのキーとstaffsのキーだけをもつテーブルです。


なるほど。
中間テーブル。。。。


テーブル名をcompany_staffにしましょう。
カラムは2つです。
company_id
staff_id


中間テーブル。。。。
そう!!
聞いたことあります?


何となくですが聞いた事があります。

ですがカラムの詳細までイメージ出来ていません。。


このテーブルに企業と従業員の関係を持たせましょう
たとえば、さっきの例と同じで、
A氏さんとB氏さんはうちなーてっくに所属します。
company_id, staff_id
1 1
1 2


はい。


うちなーてっくのpk => 1
A氏さんのpk => 1
B氏さんのpk => 2


すいません、pkはどういう意味ですか?


プライマリキーです!

了解です!!


うちなーてっくのpkは1なのでcompany_idに1


このcompany_idカラムが移行した感じです
データを挿入しましょう!
id, company_id, name, birth_day
1, 1, A氏, 19900901
2, 1, B氏, 1500505,
3, 3, 友田, 19950501


OKです!


では、友田がうちなーてっくに所属するを
company_staffテーブルにレコードを挿入するとどうなりますか???
company_id
staff_id
の値を教えてください!


company_id 1
staff_id 2


だと思います!


友田のidは3です!


2はB氏ですね!


あ!
すいません!勘違いしてました!

友田さんなので3です!!


そうです!!
こうなりましたね!!
company_id, staff_id
1 1
1 2
1 3
友田が翌日、Googleにも所属しました!
どうなりますか?

company_id, staff_id
1 1
1 2
1 3
3 3


正解です!!
A氏さんが、Facebookにも所属したときは?


そうです!!!


会社が無限に増えても、staffsテーブルにカラムを追加せずに
済むのわかりますか?


company_staffテーブルにレコードを追加するだけでいいんですよ


わかります!!
理解できました!


これが、中間テーブルで多対多を表します!!


これが多対多。。
なるほど。。。

ここまでOK?

OKです!!

では、インフルエンサーポータルで考えましょうか!


はい!


今回のミッションは、
ユーザが活動地域を登録することでしたね?


はい!

活動地域とは都道府県です。
ユーザと活動地域との関係をみていきましょう!!
ユーザは複数指定できるんでしたっけ?







皆さん!そんな我々と一緒に働きませんか??
現在、WEBエンジニア、フロントエンジニア、
セキュリティエンジニア、プロジェクトマネージャーと
4つの職種で募集しております。

詳細はこちらをご覧頂き、ご興味のある方は是非ご応募下さい。
スタッフ一同お待ちしております。

最後まで、読んでくださりありがとうございました。

最後までお読みいただきありがとうございました