雰囲気で理解するデータベースの正規化(初心者向け)

#はじめに
基本情報の試験でも出題されるデータベースの正規化についてまとめました。
本記事は基本情報試験レベルの正規化の問題がわからない方に向けて、出来るだけ専門用語を使わずに説明したいと思います。
具体的には[基本情報試験技術者試験ドットコム](https://www.fe-siken.com/kakomon/20_aki/q57.html)の解説を見ても理解が難しい方向けです。

なお、しっかりとした解説が欲しい方は一番下に記載してある「参考にさせていただいたサイト」の方をお読み下さい。わかりやすく説明してありオススメです。


#正規化とは
専門用語を使った説明は難しいので簡単にまとめると、
「整理されていないデータを項目ごとに分割していき、無駄を省いていく」というイメージです。
正式な定義を知りたい方は各自で調べるようにお願いします。

#正規化の手順
全く整理されていない「非正規系」から「第一正規系」「第二正規系」「第三正規系」といった順番に正規化していきます。
実際に基本情報試験の過去問を利用しながら解説していきます。

##基本情報技術者試験の問題
平成20年秋期問57を使って説明します。
<img width="689" alt="スクリーンショット 2019-12-30 3.46.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386463/65ac72d6-f7d8-f482-302b-5799114e62e7.png">

##非正規系
繰り返しの表記が存在するものは非正規系です。
そのため基本情報試験に出題されているものは非正規系となります。
問題文だけでは少しわかりにくいかもしれないので、実際に適当な値を入れてテーブルを作ってみます。

<table>
<tr>
	<th>伝票番号</th><th>日付</th><th>顧客コード</th><th>顧客名</th><th>住所</th><th>商品コード</th><th>単位</th><th>数量</th><th>単価</th>
</tr>
<tr>
<td rowspan="3">123</td><td rowspan="3">2019/10/12</td><td rowspan="3">D2367</td><td rowspan="3">アップル社</td><td rowspan="3">東京都</td><td>C9876</td><td>個</td><td>12</td><td>100</td>
</tr>
<tr>
<td>C7245</td><td>個</td><td>5</td><td>500</td>
</tr>
<tr>
<td>C6592</td><td>箱</td><td>2</td><td>300</td>
</tr>
<tr>
<td>456</td><td>2019/10/13</td><td>D4352</td><td>オレンジ社</td><td >大阪府</td><td>C9876</td><td>個</td><td>4</td><td>100</td>
</tr>
<td>789</td><td>2019/10/14</td><td>D1869</td><td>グレープ社</td><td >愛知県</td><td>C7245</td><td>個</td><td>6</td><td>500</td>
</tr>
</table>


伝票番号123のデータは繰り返しのデータを持っているのがわかると思います。


##第一正規系
第一正規系は簡単で繰り返しの表記を消去し、全てのデータを一つずつ記載します。
以下が第一正規系のテーブルです。(繰り返しの部分を分けて表示した)

<table>
<tr>
	<th>伝票番号</th><th>日付</th><th>顧客コード</th><th>顧客名</th><th>住所</th><th>商品コード</th><th>単位</th><th>数量</th><th>単価</th>
</tr>
<tr>
<td>123</td><td>2019/10/12</td><td>D2367</td><td>アップル社</td><td >東京都</td><td>C9876</td><td>個</td><td>12</td><td>100</td>
</tr>
<tr>
<td>123</td><td>2019/10/12</td><td>D2367</td><td>アップル社</td><td >東京都</td><td>C7245</td><td>個</td><td>5</td><td>500</td>
</tr>
<tr>
<td>123</td><td>2019/10/12</td><td>D2367</td><td>アップル社</td><td >東京都</td><td>C6592</td><td>箱</td><td>2</td><td>300</td>
</tr>
<tr>
<td>456</td><td>2019/10/13</td><td>D4352</td><td>オレンジ社</td><td >大阪府</td><td>C9876</td><td>個</td><td>4</td><td>100</td>
</tr>
<td>789</td><td>2019/10/14</td><td>D1869</td><td>グレープ社</td><td >愛知県</td><td>C7245</td><td>個</td><td>6</td><td>500</td>
</tr>
</table>



ここで少し主キーについて説明します。
主キーとはデータを識別するためのものです。主キーに対して他のデータは紐づいています。
そのため主キーは**重複しない**、**NULLにならない**という特性を持ちます
また、主キーは複数存在することもあります。

問題文から伝票番号は主キーということがわかります。
しかし、上の表からでもわかる通り同一の伝票番号が複数存在するので**主キーは重複しない**に反してしまいます。
つまり主キーは伝票番号以外にも存在するということになります。ここでは商品コードも主キーとなります。

よって第一正規系は以下のようになります。

<table>
<tr>
	<th>伝票番号*</th><th>日付</th><th>顧客コード</th><th>顧客名</th><th>住所</th><th>商品コード*</th><th>単位</th><th>数量</th><th>単価</th>
</tr>
</table>



(\*)記号は主キーを示します。

##第二正規系
正規系が苦手な方の多くはここで躓くと思います。
第二正規系は主キーに注目します。ここでは伝票番号と商品コードです。

まずは主キーに対して紐づいているデータを探します。
伝票番号は日付、顧客コード、顧客名、住所に紐づいています。
商品コードは問題文にも記載されている通り単価、単位に紐づいています。

ここで新たに伝票番号と商品コードのテーブルを作成します。


<table>
<tr>
	<th>伝票番号</th><th>日付</th><th>顧客コード</th><th>顧客名</th><th>住所</th>
</tr>
<tr>
<td>123</td><td>2019/10/12</td><td>D2367</td><td>アップル社</td><td >東京都</td>
</tr>
<tr>
<td>456</td><td>2019/10/13</td><td>D4352</td><td>オレンジ社</td><td >大阪府</td>
</tr>
<td>789</td><td>2019/10/14</td><td>D1869</td><td>グレープ社</td><td >愛知県</td>
</tr>
</table>

<table>
<tr>
	<th>商品コード</th><th>単位</th><th>単価</th>
</tr>
<tr>
<td>C9876</td><td>個</td><td>100</td>
</tr>
<tr>
<td>C7245</td><td>個</td><td>500</td>
</tr>
<tr>
<td>C6592</td><td>箱</td><td>300</td>
</tr>
</table>

第一正規系からこの2つの表の主キー以外の部分を削除すると以下のような表になります。


<table>
<tr>
	<th>伝票番号</th><th>商品コード</th><th>数量</th>
</tr>
<tr>
<td>123</td><td>C9876</td><td>12</td>
</tr>
<tr>
<td>123</td><td>C7245</td><td>5</td>
</tr>
<tr>
<td>123</td><td>C6592</td><td>2</td>
</tr>
<tr>
<td>456</td><td>C9876</td><td>4</td>
</tr>
<td>789</td><td>C7245</td><td>6</td>
</tr>
</table>

よって第二正規系は以下のようになります。

<table>
<tr>
	<th>伝票番号*</th><th>日付</th><th>顧客コード</th><th>顧客名</th><th>住所</th>
</tr>
<tr>
	<th>商品コード*</th><th>単位</th><th>単価</th>
</tr>
<tr>
	<th>伝票番号*</th><th>商品コード*</th><th>数量</th>
</tr>

</table>

##第三正規系

第三正規系は先ほど第二正規系で行った動作を主キー以外にも適用させます。
ここでは顧客コードが顧客名、住所に紐づいています。
よって第二正規系の伝票番号の部分を以下のように分けることができます。

<table>
<tr>
	<th>顧客コード</th><th>顧客名</th><th>住所</th>
</tr>
<tr>
<td>D2367</td><td>アップル社</td><td >東京都</td>
</tr>
<tr>
<td>D4352</td><td>オレンジ社</td><td >大阪府</td>
</tr>
<td>D1869</td><td>グレープ社</td><td >愛知県</td>
</tr>
</table>


<table>
<tr>
	<th>伝票番号</th><th>日付</th><th>顧客コード</th>
</tr>
<tr>
<td>123</td><td>2019/10/12</td><td>D2367</td>
</tr>
<tr>
<td>456</td><td>2019/10/13</td><td>D4352</td>
</tr>
<td>789</td><td>2019/10/14</td><td>D1869</td>
</tr>
</table>


これにより第三正規系は以下のようになります。


<table>
<tr>
	<th>伝票番号*</th><th>日付</th><th>顧客コード</th>
</tr>
<tr>
	<th>伝票番号*</th><th>商品コード*</th><th>数量</th>
</tr>
<tr>
	<th>商品コード*</th><th>単位</th><th>単価</th>
</tr>
<tr>
	<th>顧客コード*</th><th>顧客名</th><th>住所</th>
</tr>
</table>

#おわりに
間違えている箇所や分かりにくい部分は指摘お願いします。

#参考にさせて頂いたサイト

[データベース　～データの正規化～](http://itsoldier0901.hatenablog.com/entry/2016/06/07/060000)

[正規化の要点を理解する](https://qiita.com/mochichoco/items/2904384b2856db2bf46c)