RDBの第2正規形について考えてみる

# はじめに
どうも、初学者です！
最近SQLを掘ってるところなので情報はしょぼいかもしれません。
が、自分が理解できるようにかなり噛み砕いて、かつ初心者さん目線になってまとめていきます！

間違いございましたら教えていただければ幸いです。

全章では、第1正規形についてまとめました!▶︎[第1正規形](https://qiita.com/yumi1003/items/4e44cc4e6e8c3aa83aa8)
今回は次なる第2正規形と第3正規形、そしてボイスコッド正規形について学習していきます！


# 第２正規形、第3正規形、ボイスコッド正規形について
第1正規形に続いて、この記事では3つの正規形が出てきました。
**第２正規形、第3正規形、ボイスコッド正規形**、この３つは全て**関数従属に基づく正規形**です。

**「関数従属...？」**

また新しい漢字が出てきたぁぁ！と思ったのですが、とっても単純です。

### 関数従属
**従属**とは、項目間(列と列の間)における依存関係のことです。
そして、例えば「Aが決まればBが決まる」という関係を**関数従属**といいます。
また、キーによって決まる項目を**従属属性**と呼びます。

具体的な例をみます。
学生時代の出席番号を思い出してください。それをRDBで保管しているとします。
自分は高校生のころ、出席番号26番でした(完璧な余談です笑)

とすると、このようになります。

|出席番号|生徒名|
|--|--|
|26|matu yumi|
これは「出席番号がわかれば、生徒氏名がわかる」ということ。
言い換えると「生徒氏名は出席番号に関数従属する」ということになります！

以上のことを踏まえて、ここから学習する3つの正規形の最終的なゴールは**「全ての列は主キーによって決まる」**ということです。

- 主キーの一部だけでなく、**主キーの全て**で決定される。
- 主キーだけで決定される。(主キー以外では決定されない！)

上記二つはしっかり意識する必要有りですね。。

## 無損失分解(無損失結合分解)
早速第2正規形に突入しよう！と言いたいとこですがその前に。
第2正規形以降はテーブルが複数に分かれます。
適切な分け方をしていれば問題ないです。しかし、項目の分け方が不適切だと、データがかけてしまったり、逆に増えてしまうことも、、
私は、分割後のテーブルに外部キーが無いってことを何度もやらかしてました。

こう言った「テーブルを分けても情報が失われないこと」を**無損失分解(または無損失結合分解)**と言います。

では今度こそ「第2正規形、第3正規形、ボイコッド正規形について」へ進みましょう！

![正規化の図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1101585/84c37e75-cd87-55c9-405d-afa306c27c3d.png)


# 3つの正規形について
先でこちらの3つの正規形は関数従属に基づいている正規形だと言いましたが、ここについて少し深堀ります。
それぞれは別の作業ですが、イメージとしては区別せずに「関数従属が隠れていないか？を探す」でいいと思います。
結局は研磨してブラッシュアップしていくのがゴールですからね！

# 第２正規形
複合キーの一部に関数従属することを、**部分関数従属**と言います。
一つのテーブルにA,B,C,Dの列があるとします。
AとBの複合キーに対し、
{A,B}→C
{A,B}→D
という従属関係があったとします。
(ここよくわからなかったら関数従属をもう一度確認することをお勧めします！)

このときDは、AとBの組み合わせだけでなく、Aによって**のみ**決まるという場合、、
Dはキー{A,B}に部分従属しています。

**第1正規形から、この部分従属を取り除いた形を第2正規形と言います！**

一見難しいことを言ってるように聞こえるかもしれませんが、例を見れば理解できるはず!

**部分従属を取り除いて第2正規形にするとはこういうこと！**

|出席番号|氏名|専攻科目|成績|
|---|--|--|--|
|001|相田 太郎|数学|A|
|002|飯田 次郎|現代文|A|
|003|上島 三郎|英語|B|

↓
↓第2正規形！
↓

|出席番号|氏名|
|---|--|
|001|相田 太郎|
|002|飯田 次郎|
|003|上島 三郎|

|出席番号|専攻科目|成績|
|---|--|--|
|001|数学|A|
|002|現代文|A|
|003|英語|B|


# 第3正規形
次に第3正規形の**推移的関数従属**とやらを取り除きます。
これも例を見ればわかると思いますのでめげずに見ていきます！

テーブルに、A,B,Cという列があります。関係性としては、
{A}→B
{A}→C
{B}→C
というものがあります。

この場合、
{A}→B
{B}→C
上記の二つから、
{A}→C
が考えられます。
このような関係を**推移的関数従属**と言います。

（´-`）...
具体的な例を見ていきましょう！

例えば、出席番号を主キーとするテーブルがあるとします。
専攻科目に対して担当教師という項目がありました。

では、出席番号1番くんの専攻科目は××、担当教師は○◯さんです。

ここで科目と担当教官に従属関係(科目が決まれば担当教師も決まるという関係)があった場合、
「{出席番号}→専攻科目」、「{専攻科目}→担当教師」となります！

|出席番号|氏名|専攻科目|担当教師|
|---|--|--|--|
|001|相田 太郎|数学|鈴木|
|002|飯田 次郎|現代文|丸山|
|003|上島 三郎|英語|桂|

↓
↓　第3正規形!
↓

|出席番号|氏名|専攻科目|
|---|--|--|
|001|相田 太郎|数学|
|002|飯田 次郎|現代文|
|003|上島 三郎|英語|

|専攻科目|担当教師|
|--|--|
|数学|鈴木|
|現代文|丸山|
|英語|桂|

出席番号から専攻科目がわかり、専攻科目から担当教師がわかる書き方になりました！
科目と担当教師は生徒と関係なく既に決まってるものですよね。だったら別においておきましょって話です。

# ボイスコッド正規形
**ボイスコッド正規形**は、第3正規形にしても尚、「まだ推移的関数従属」があるという発見から作られた正規形です。
「え、でも正規化したよ..?」 と思いましたが実は、、

第3正規形では、**キーに対して**の推移的関数従属は取り除きましたが、**「キーでもあり、他の項目への関係従属もしている」**という項目が排除できていません。
そこで使うのが**ボイスコッド正規形**です！
({A,B},C,D)というテーブルにおいて、
{C}→A
{D}→A
という形を無くした形です。

具体例を見ていきます。
下記の例では数学担当教師が二人いる状態になっています。

↓主キーはこの2つ↓

|出席番号|専攻科目|担当教師|
|--|--|--|
|001|数学|鈴木|
|001|数学|桜井|
|002|現代文|丸山|
|003|英語|桂|

↓
↓ボイスコッド正規化!
↓

|出席番号|担当教師|
|--|--|
|001|鈴木|
|002|桜井|
|003|丸山|
|004|桂|
↑主キーは出席番号

|担当教師|科目|
|--|--|
|鈴木|数学|
|桜井|数学|
|丸山|現代文|
|桂|英語|
↑主キーは担当教師

下2つのテーブルはJOINすることで、上のテーブルをビューとして表示することができます！
※正規化でテーブルを分けたときは、SELECT文で元のテーブルのデータを表示できるのかを確認するのが大切になります！

# まとめ
ここまでの学習で~従属と色々出てきましたが、これを覚えるよりかは、このルールを覚えることに力を入れることが大切だとわかりました。
指差し確認しながら正規化できるように頑張ります！


**チェック項目「XによってYが決まる」とき**

- Xがキーになっているか
- Xだけがキーになっているか
- Xに従属しない属性がないか