初心者がデータベース設計を勉強してみた

# はじめに
筆者は大学生3年生でWeb開発のエンジニアを目指している者です。
Webアプリケーションを今までなんとなく作成していましたが、データベースの設計をしっかり考えてから作り始めたところ、全く理解をしていないことに気づき勉強を始めました。

なので、学んだことをまとめるために記事を書いてみようと思います。

下にあるYoutubeの内容をまとめていきます。

# 参考にみた記事や動画

https://youtu.be/Yg546Zua39A

https://www.youtube.com/watch?v=T6g-DLWHscw

https://www.youtube.com/watch?v=WEmY9s0Ky88


# データベースとは

簡単にいうと、データを管理するシステムのこと。

そしたら、次にこのような疑問が出ると思います。
**データをどのように管理しているか？**

テーブルというexcelやスプレッドシートのような2次元表みたいなものを利用して、管理している。

# テーブルの構造について

生徒テーブル
| ID | 名前 | 苗字 |
| :-: | :-: | :-: |
| 1 | ゴン | フリークス |
| 2 | キルア | ゾルディック |
| 3 | クラピカ |  |
| 4 | レオリオ | パラディナイト |
| 5 | ジン | フリークス |

横の **1 ゴン** を行(レコード)
縦の **ゴン キルア クラピカ レオリオ**を列(カラム)
と言います。

主キー(プライマリーキー)というものがあります。
主キーとは、テーブルの中で唯一無二のもの
つまり、ユニークなものです。
上記の生徒テーブルで`ID == 1`の情報を取ってくると **`ゴン`**　の値などが返ってくる。
被りがなく、レコードの情報を全て特定できるもののことを指す。

例えば、上のテーブルでみた時に`フリークス`の情報を取ってこい！としたら、 ***ゴンとジン***が返ってきます。ですが、**IDで指定**したら、２つの値が返ってくることはありません。
なので、IDは主キーとなります。

# 実際にデータベースの設計してみる

## 設計でやるべきこと
***・何をデータとして保存するか？
・どのような形式で保存するか？
・横方向での繰り返しを無くすには？
・縦方向での繰り返しを無くすには？***

# 今回のお題 ： みんなの時間割

| 小野時間割 | 小野マイページ | 内田時間割 | 内田マイページ |
|:------------:|:------------:|:------------:|:------------:|
| 1.心理学 | 学部：1.農学部 | 2.栄養学 | 学部：3.工学部 |
| 2.栄養学 |  |  |  |

### STEP.1 何をデータとして保存するか？

上の表の中で何がデータになるのかを考えてみる。
まず、**小野**は名前だからデータになる。
次に、**心理学**や**栄養学**も人によって変わるからこれもデータになる。
マイページの方も見てみる。すると、**学部**も個人個人で変わるものとなる。
これもデータとして扱うことができる。

:::note info
何をデータとして保存する
・システムで使用するもの(商品情報など)
・ユーザーが登録するもの(氏名など)
:::

#### データになるもの

・**生徒の名前**：小野/内田
・**科目ID/科目名**：1.心理学/2.栄養学
・**学部ID/学部名**：1.農学部/3.工学部

これで何がデータになるかの把握ができました。

:::note info
ポイント：最初にやること
・データの抽出
・テーブルを定義する
:::

### STEP.2 どのような形式で保存するか？

まずは、さっきあげたデータ全てを一つのテーブルに入れてみる

| 名前 | 科目ID | 科目名 |科目ID | 科目名 | 学部ID | 学部名 |
|:----:|:----:|:----:|:----:|:----:|:----:|:----:|
| 小野 | 1 | 心理学| 2 | 栄養学  | 1 | 農学部 |
| 内田 | 2 | 栄養学 |  |  | 3 | 工学部 |

2行目の小野と1行目の小野は違う人だが、データとしては一意には特定できない。
生徒IDをつけてあげたら一意に特定できるようになる。

| 生徒ID | 名前 | 科目ID | 科目名 |科目ID | 科目名 | 学部ID | 学部名 |
|:----:|:----:|:----:|:----:|:----:|:----:|:----:|:----:|
| 1 | 小野 | 1 | 心理学| 2 | 栄養学  | 1 | 農学部 |
| 2 | 内田 | 2 | 栄養学 |  |  | 3 | 工学部 |

:::note info
ポイント：主キーが必要になる
・値を指定すれば、1行のレコードを特定できる
・テーブル内に必ず1つだけ存在
・主キーは重複データを持てない
:::

これでデータベース設計は完了したように思えますが、まだまだ課題があります。

# 検索から課題を考えてみる

この状態では科目IDが***横方向***連続しています。
なので、科目で分割して一列になるようにしてみます。

| 生徒ID | 名前 | 科目ID | 科目名 | 学部ID | 学部名 |
|:----:|:----:|:----:|:----:|:----:|:----:|
| 1 | 小野 | 1 | 心理学 | 1 | 農学部 |
| 1 | 小野 | 2 | 栄養学 | 1 | 農学部 |
| 2 | 内田 | 2 | 栄養学 | 3 | 工学部 |

小野の**生徒ID・名前・学部ID・学部名**が重複しています。
科目IDと科目名のところが重複しないようになっているため、ここを新たなテーブルとして作成します。

***生徒テーブル***
| 生徒ID | 名前 | 学部ID | 学部名 |
|:----:|:----:|:----:|:----:|
| 1 | 小野 | 1 | 農学部 |
| 1 | 小野 | 1 | 農学部 |
| 2 | 内田 | 3 | 工学部 |

***科目テーブル***
| 生徒ID | 科目ID | 科目名 |
|:----:|:----:|:----:|
| 1 | 1 | 心理学 |
| 1 | 2 | 栄養学 |
| 2 | 2 | 栄養学 |

生徒IDをキーに生徒テーブルと紐付けを行います。

次に縦方向で被っているところをテーブル化していきます。

生徒テーブルにある学部IDや学部名も別テーブルに切り出します。
さらに科目テーブルも科目IDと科目名で切り出します。(これが中間テーブルになります。)

***生徒テーブル***
| 生徒ID | 名前 | 学部ID |
|:----:|:----:|:----:|
| 1 | 小野 | 1 |
| 2 | 内田 | 3 |

***学部テーブル***
| 学部ID | 学部名 |
|:----:|:----:|
| 1 | 農学部 |
| 3 | 工学部 |

***科目リレーションテーブル***
| 生徒ID | 科目ID |
|:----:|:----:|
| 1 | 1 |
| 1 | 2 | 
| 2 | 2 |

***科目テーブル***
| 科目ID | 科目名 |
|:----:|:----:|
| 1 | 心理学 |
| 2 | 栄養学 |

生徒テーブルに学部IDを置いたことで、生徒テーブルと学部テーブルの繋がりを作りました。
生徒テーブルと科目テーブルの中間テーブルとして***科目リレーションテーブル***を作成しました。
このテーブルには***生徒ID***と***科目ID***を置いて
この***生徒テーブル***と***科目テーブル***と繋がりを作りました。

このように分けることができます。
これでテーブル設計は***完成***です。

# ER図で書いてみた

上記のテーブルの書き方では見にくいので***ER図***にして書いてみました。

https://www.lucidchart.com/pages/ja/examples/ER-diagram-tool

こちらのサイトを使いました。

![bda5fa65-da55-1552-0801-9fad3a3da152.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1803665/1d7ae6da-0225-50f4-e7ff-14feb939c14c.png)

***1対1・n対n・1対n***の関係性はこちらの記号を用いて書きます。
以下の写真のようになります。

![データベース ER 図 (カラスの足記法).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1803665/120fc9b0-33f6-723a-3b3c-ef2feaa562c2.png)



# 最後に
著者はフロントエンドエンジニアもしくはバックエンドエンジニアを目指して日々勉強中の大学生です。
間違っている点がありましたらご指摘頂けると助かります。

データベース設計はアプリ作成において命だなと感じました。
テーブル設計でどのように分けるべきか
しっかり考えて、アプリ作成をできるようになれば、さまざまな機能をつけていけるなと感じました。

より良いデータベース設計をできるように学んでいきたいなと思います。