ER図の作り方まとめ

こんにちは。ネオシステムの高橋です。
今回はER図の作成についてまとめたいと思います。
以前にご紹介した記事では[データ項目](https://qiita.com/szn-t/items/22e5e223fe56bf7e0c48#%E3%83%87%E3%83%BC%E3%82%BF%E9%A0%85%E7%9B%AE%E3%81%AE%E4%BD%9C%E6%88%90)を洗い出しました。
今回の記事ではデータ項目をより具体化し、データモデルの作成まで紹介します。
[業務フロー図の記事](https://qiita.com/szn-t/items/22e5e223fe56bf7e0c48)も併せてご活用ください。

# 目次
- ER図を構成する要素
- リレーション
- マスタとトランザクション
- レコードの削除
- まとめ

# ER図を構成する要素

ER図を作成する前に、用語を確認しておきましょう。

- エンティティ
    - データのまとまりのこと
    - テーブルとも呼ばれる
- アトリビュート
    - エンティティの中の属性情報のこと
    - カラムとも呼ばれる
    - 主キーはエンティティ上部で四角で囲い、<PK>と書く
    - 外部キーは項目名の後ろに<FK>と書く　※FOREIGN KEYの略
- リレーション
    - エンティティ同士の関係を表現する線
    - 「一対多」「多対一」「多対多」のうちどれか
- カーディナリティ
    - 「0か1」「1のみ」「0以上」「1以上」のうちどれか

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599668/4d544814-e27a-7682-3ecc-ecd5c0752190.png)


# アプリ開発に必要な項目を抜き出す
どのようなデータが必要かを探るには[こちらの記事](https://qiita.com/szn-t/items/22e5e223fe56bf7e0c48#%E3%81%A9%E3%81%AE%E3%82%88%E3%81%86%E3%81%AA%E3%83%87%E3%83%BC%E3%82%BF%E3%81%8C%E5%BF%85%E8%A6%81%E3%81%8B)を参考にしてみてください。
今回はその記事で作成したデータ項目を使っていきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599668/a89d760c-cc4f-1749-6bb0-569ff054d6f6.png)

今回は3つのデータレベルをそれぞれのエンティティとして考えます。
その中で不足しているデータ項目を追加します。
- 報告書表紙
- 報告書
- 報告書明細

![testname.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599668/a020a9cc-8d8e-e332-680e-fcd86bba2ff9.png)

# リレーション
3つのエンティティの関連性を考えます。
この中で親子関係がないか探していきましょう。

## 報告書表紙と報告書のリレーション
ここで、報告書表紙と報告書がどのように作成されるか考えます。
- 基本的な作業は表紙を先に作成して後から報告書を紐づける
- 先に報告書を貯めておき、最後に表紙をつけるパターンもある
- 報告書表紙1枚に複数の報告書が紐づく

以上のことから**報告書表紙 : 報告書 = 0か1 : 0以上**となります。

## 報告書と報告書明細のリレーション
ここでも、報告書と報告書明細がどのように作成されるか考えます。
- 必ず先に報告書を作成する、その際に明細も1件以上併せて作成する
- 報告書1枚に複数の明細が紐づく

以上のことから**報告書 : 報告書明細 = 1のみ : 1以上**となります。


## ER図にリレーションを追加

2つの関係性をER図で示すとこのようになります。
リレーションを張った後は、子エンティティに外部キーを追加しましょう。
このER図でいうところの`<FK>`が外部キーにあたります。

![testname.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599668/b28dd330-4566-2c13-40be-92df32a34f66.png)

# マスタとトランザクション
データは大きく2つに分けられます。

## マスタデータ
- アプリ開始前から入れておくデータ
- データの追加更新削除の頻度は低い
- 親子関係の親になりやすい

## トランザクションデータ
- システムを使っていくと増えていくデータ
- データの追加更新削除の頻度は高い
- 親子関係の子になりやすい

上で作成したER図にはトランザクションデータを入れるエンティティしかない状況です。

## マスタとトランザクションに分ける
ER図の中にマスタデータとして管理すべきところはないか探してみましょう。
今回は**社員マスタ**と**事業所マスタ**を用意することにしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599668/070f9ded-a559-7342-7620-7c124d56bb0f.png)


マスタデータを用意することで、報告書や表紙を作成するときに、都度社員名や事業所を入力する手間が省けます。

## リレーションの追加
上と同様、作成したマスタと既存のエンティティにリレーションを張りましょう。

### 報告書表紙と事業所マスタのリレーション
報告書表紙エンティティには事業所名という属性情報を持っていました。
報告書表紙エンティティと事業所エンティティの親子関係を築くことで、事業所情報をマスタから参照することができます。

- あらかじめ事業所マスタデータを用意しておく
- 報告書表紙作成時、事業所情報を必ず選択する

以上のことから**事業所 : 報告書表紙 = 1のみ : 0以上**となります。

### 報告書と社員マスタのリレーション
報告書エンティティには点検者1~5の属性情報があります。
これらの情報も社員マスタと親子関係を築くことで、マスタから情報を参照することができます。

- あらかじめ社員マスタデータを用意しておく
- 報告書作成時、点検者を1名以上入力する
- 1枚の報告書で記載する点検者は2名～5名ほどであり、人数を固定できない

以上のことから**社員 : 報告書 = 1以上 : 0以上**となります。


### 事業所と社員のリレーション
マスタ同士にもリレーションを張ることができます。
同じマスタでも、データの更新頻度が高いのはどのマスタか考えましょう。
- 事業所マスタデータを先に用意しておく
- アプリ開始以降、事業所マスタデータを作成更新削除する予定はなし
- 社員情報は年度初めに必ずメンテナンスする
- 社員情報登録時は事業所を必ず設定する

以上のことから**事業所 : 社員 = 1のみ : 0以上**となります。

## ER図にリレーションを追加

マスタデータを追加しリレーションを張った結果、このようになりました。

![testname.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599668/d1bbb574-bff1-4601-614a-0618976d2ddd.png)

## 多対多のリレーションは中間テーブルを設ける
概念としてER図を作成している場合は上のER図で完成ですが、物理的なデータ構造を表現したい場合は、もう1ステップの修正が必要です。

多対多のリレーションがある場合は中間テーブルを設けて、どこにどのようなデータを格納するのか明確にしておきましょう。
今回は社員と報告書の間に点検者という中間テーブルを追加しました。
報告書と社員が親、点検者が子という関係になります。

![testname.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599668/99cfbeee-2a64-b67e-aba2-800f4ecc270c.png)

## リレーションまとめ

マスタデータを用意すると固定の情報と頻繁に動く情報を分けられるので、データの重複を防ぐことにつながり、汎用性の高いデータを蓄積することができます。
一方で、たくさんのマスタを設計すると、データを用意するのに時間がかかったりメンテナンスが難しくなったりするので、適切なボリュームに調整しましょう。


# レコードの削除
エンティティ間でリレーションを張るとき、親のデータが削除された場合は子データにどう影響するのか考えます。
3つのパターンを紹介します。

## ①外部キー制約
子を持つ親データは削除できないという制約を外部キー制約といいます。
また子データが親を指定する際は、存在する親データしか指定できなくなる制約でもあります。
この制約は親子関係の整合性が保たれるので、不用意な削除を防ぐことができますが、親が頻繁にデータが削除される場合は向かないパターンと言えます。

## ②親の削除処理が子にも伝搬される
親データを削除すると、子データも一括で削除されるパターンです。
外部キー制約は削除制限がかかりましたが、今回のパターンは不用意な削除を防ぐことができなくなるため注意が必要です。

## ③親を削除すると子のリンクが削除される
親データを削除しても子データは残るパターンです。
ER図で子データは0以上のカーディナリティを選択しておかないと、このパターンは選択できなくなります。

## 削除パターンまとめ
ER図にあるリレーションにおいて、それぞれどの削除パターンが望ましいか検証してみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599668/5add08a6-de00-4a79-2997-ef15834e8f34.png)

## 論理削除
不用意なデータの削除を防ぐために、データを論理的に削除する方法があります。
例えば削除フラグや廃止フラグを設けることで、物理的には存在するがデータとして扱わないようにする仕組みを用意することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599668/080a1f48-3b5d-732c-84c6-45b9dabe240a.png)


誤った削除処理を取り消すことができる一方、データ容量が圧迫されたりデータのフィルタリングが複雑になったりするなどデメリットもあるので、論理削除か物理削除か見極める必要があります。

# まとめ
これまでに何回かER図を作成した経験がありますが、カーディナリティの選択が一番難しいと感じました。
自分は親子関係をイメージするとわかりやすかったので、今回は「親子」という言葉で例えています。
実際にトランザクションデータを登録するタイミングや順序によって、0はありなのかどうか判断するポイントになりますので、利用シーンのイメージができてからER図を作成することをお勧めします。

次回の記事は[WBSを作る前に知っておきたいこと](https://qiita.com/szn-t/items/3b6e46560c482b62d620)についてまとめています。
こちらも併せてよろしくお願いします。