データベースの正規化について

##はじめに
wikipediaで関係の正規化を読んでいて、中々理解が出来なかったので、第1～第5正規形とボイス・コッド正規形についてまとめます。

##正規化とは？
データの重複を排除し、整合性と効率性を持たせること。

##メリット
・データの変更時に生じるデータ不整合を防げる。
・データを変更するときに最小限の労力でできる。
・テーブルの持つ意味が明確になる。
・メンテナンスの効率化を図ることができる。

##デメリット
・アクセス速度が低下する場合がある。
・テーブルが増える。
・SQL文が複雑になる可能性がある。

##非正規形
正規化が行われておらず、1行の中に複数の繰り返し項目が存在すること。


例1：繰り返し現れる列があるパターン
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587966/3ac772fb-0a48-c9da-65a4-40cd9900f87b.png)

例2：1つのフィールドに複数の値があるパターン
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587966/7c76350e-57bf-d730-5296-a214abb549b4.png)

##第1正規形
関係がスカラ値のみを持つもの。

**第1正規形にするには以下の処理をする。**
・一つのフィールドに一つの値のみにする。
・繰り返し現れる列を別の表に分割する(同じ意味を持つ列を複数作らない)。
・導出項目を削除する(他の項目から算出できるため、冗長になる)。

※スカラ値：それ以上分割できない単一の値のこと。
※導出項目：他の列から算出できる項目のこと。

**非正規形の例1または、例2を正規化すると以下のようになる。**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587966/56e81966-f4b3-cb6a-c992-29fd8e3f000d.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587966/dd913f65-0466-fdd9-3e65-ad47a5f680b0.png)
・例1は繰り返し現れる列を、例2は一つのフィールドに複数の値あるものを注文票と注文明細に分割。
・列の「金額」は「単価*数量」で算出できるため削除。

##第2正規形
第1正規形の表から部分関数従属性を排除し、主キー列の値が決まれば主キー以外の列の値が決まるような表に分割したもの。

**第2正規形にするには以下の処理をする。**
・第1正規形の表にする。
・複合主キーがある表は片方のみに関数従属する列を別の表に分割する。
・主キー列の値が決まれば非キー(主キー以外)の列の値が決まるようにする。

※関数従属性：「ある列の値Xが決まると、別の列の値Yが自動的に決まる」という関係。
※部分関数従属性：AとBからなる複合主キーの場合、「AまたはBが決まるとYが決まる」という関係。


**第1正規化したものを第2正規化すると以下のようになる。**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587966/c7cba462-f1e3-d433-e0c3-0289d1648615.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587966/38c80b87-09fe-c980-c84f-a5052c5ec925.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587966/a9836d58-8f8d-70f3-b138-c09316272215.png)
注文票は以下のため、分割しない。
・複合主キーがないため部分関数従属性があるものはないと判断できる。
・主キーである注文ID列の値が決まれば非キー(主キー以外)列の値が全て決まる。

注文明細表は以下のため、注文明細表と商品表に分割する。
・商品ID(複合主キー)のみに商品名と単価が関数従属する。

##第3正規形
第2正規形の表から推移関数従属性を排除したもの。

**第3正規形にするには以下の処理をする。**
・第2正規形の表にする。
・非キーに関係従属する非キーの列を別の表に分割する。

※推移関数従属性：以下条件を満たすときの関係(Xは主キー、Y、Zは非キーとする)。
・「Xが決まるとYが決まり、Yが決まるとZが決まる」、「Xが決まると、Zが決まる」が成立する。
・「Yが決まると、Xが決まる」、「Zが決まると、Xが決まる」は成立しない。

**第2正規化したものを第3正規化すると以下のようになる。**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587966/89922f75-74c8-63a4-4b4d-5c9ce248f9b1.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587966/c106d8b9-89ba-8a90-1320-088414149698.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587966/f7752a79-c004-24a1-56e6-90497a345e7a.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587966/e66b2a32-eef1-2fbd-b982-401c93d31b38.png)

注文票は以下のため、注文票と顧客表に分割する。
・注文ID(主キー)に顧客ID(非キー)が関数従属する。
・顧客ID(非キー)に、顧客名(非キー)、顧客住所(非キー)、電話番号(非キー)が関数従属する。

注文明細表と商品表は以下のため、分割しない。
・非キー間での関数従属性が含まれていない。

##ボイスコッド正規形
第3正規形の表から非キーへ関数従属する主キーの関係を排除したもの。

**ボイスコッド正規形にするには以下の処理をする。**
・第3正規形の表にする。
・非キーが決定項で複合主キーの片方が従属項のものは別の表に分割する。

※決定項：「Xが決まると、Yが決まる」のXのこと(Yは従属項)。

**ボイスコッド正規化の例**
以下を要件とする
・受講者とコース名が決まると講師が決まる。
・一人の講師は一つのコースを担当する。
・一人の受講者は複数のコースを受講することができる。

正規化前
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587966/8e87feb0-dbf4-8624-51bc-8c5ff337613c.png)
正規化後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587966/6656ce43-42a1-601c-33ce-75b7d4c8312a.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587966/73600132-f8ba-0742-2448-6bd12a89917a.png)
・非キー列の講師に主キー列のコース名が関数従属するため、受講者と担当講師に分割する

##第4正規形
表の列が全て主キーで、自明でない多値従属性を排除したもの。
※第4正規形の条件を満たしたときは、基本的に第5正規形を満たす

**第4正規形にするには以下の処理をする。**
・全ての列が主キーの表にする。
・「1対n」の関係を持つ列が1組になる表に分割する。

※多値従属性：Aが決まるとBの集合が決まる関係のこと(「1:n」の関係)。
※自明でない多値従属性：一つの表の中に複数の多値従属性が存在すること。
※自明な多値従属性：一つの表の中に一つの多値従属性が存在すること。

**第4正規化の例**
正規化前
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587966/e7eff63c-c2be-f5c0-4f94-fc3df6981786.png)
正規化後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587966/d653c87b-33a8-fd0c-bc93-4e50574cebca.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587966/65c4d12a-324e-8a9c-962e-ed175d3810d6.png)
以下のため、表を分割する。
・表の列が全て主キーで、非キーが存在しない。
・「業種と商品名、業種と社名」と一つの表に複数の多値従属性がある。

##第5正規形
第4正規形で、自明でない結合従属性を排除したもの。

**第5正規形にするには以下の処理をする。**
・第4正規形の表にする。
・分割した表を元の表に戻せるようにする。

※結合従属性：分解した表を、元の表に戻すことができる性質のこと。
※自明でない結合従属性：分割した表を、元の表に戻すことができないこと。

**第5正規化の例**
正規化前
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587966/d0071e81-458a-5da5-3ef7-7b03b47f8f10.png)
正規化後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587966/bb9e6247-159c-8a7d-7d88-755df8136ddb.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587966/6d116159-cf97-7b18-3777-979508dcc08b.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587966/79978365-3edd-2407-bf25-62eab4a18c29.png)
以下のため、表を分割する。
・表の列が全て主キーで、非キーが存在しない。
・「店名と料理名、店名と食材、料理名と食材」と一つの表に複数の多値従属性がある。

##最後に
最後までご覧いただき誠にありがとうございます。
今回、第1～第5正規形とボイス・コッド正規形についてまとめてみましたが、正直なところ第4～第5正規形はまだ理解があやしいです。
ですので、間違っているところがありましたら、ご指摘いただければ幸いです。

##参考記事
[関係の正規化](https://ja.wikipedia.org/wiki/%E9%96%A2%E4%BF%82%E3%81%AE%E6%AD%A3%E8%A6%8F%E5%8C%96)
[RDBの正規化理論](https://xtech.nikkei.com/it/article/COLUMN/20070802/278945/)
[「特殊な正規形」を理解する](https://atmarkit.itmedia.co.jp/ait/articles/1703/01/news183.html)