正規化 — 1つの事実は、1か所だけに書く
1枚の表に何でも詰め込むと、最初は楽です。でも同じ情報があちこちに重複し、「みかんの単価が変わったら何十行も直す」「商品が売り切れて行が消えたら商品情報まで消える」といった事故が起きます。正規化は、この重複とムダを段階的に取り除くための手順です。グチャグチャな1枚の表を、ハサミで小さな表に切り分け、IDで紐づけ直していきます。
下の図1のステップを 非正規形 → 1NF → 2NF → 3NF と順に進めてみてください。各ステップでどの重複が消えるかを、ハイライトと一緒に確認できます。
注文表(ぜんぶ1枚)
| 注文ID | 顧客名 | 住所 | 商品 |
|---|---|---|---|
| 1001 | 田中 | 東京 | りんご, みかん |
| 1002 | 佐藤 | 大阪 | みかん |
注文表(1セル=1値に)
| 注文ID | 顧客名 | 住所 | 商品名 | 単価 | 個数 |
|---|---|---|---|---|---|
| 1001 | 田中 | 東京 | りんご | 120 | 2 |
| 1001 | 田中 | 東京 | みかん | 80 | 3 |
| 1002 | 佐藤 | 大阪 | みかん | 80 | 1 |
注文
| 注文ID | 顧客名 | 住所 |
|---|---|---|
| 1001 | 田中 | 東京 |
| 1002 | 佐藤 | 大阪 |
注文明細
| 注文ID | 商品名 | 個数 |
|---|---|---|
| 1001 | りんご | 2 |
| 1001 | みかん | 3 |
| 1002 | みかん | 1 |
商品マスタ
| 商品名 | 単価 |
|---|---|
| りんご | 120 |
| みかん | 80 |
注文
| 注文ID | 顧客ID |
|---|---|
| 1001 | C1 |
| 1002 | C2 |
顧客マスタ
| 顧客ID | 顧客名 | 住所 |
|---|---|---|
| C1 | 田中 | 東京 |
| C2 | 佐藤 | 大阪 |
注文明細
| 注文ID | 商品名 | 個数 |
|---|---|---|
| 1001 | りんご | 2 |
| 1001 | みかん | 3 |
| 1002 | みかん | 1 |
商品マスタ
| 商品名 | 単価 |
|---|---|
| りんご | 120 |
| みかん | 80 |
図1 — ステップを進めるたびに表が切り分けられ、重複(色つきセル)が消えていく
各ステップで何を直しているのか
1NF(第1正規形)は「1つのセルに値を1つだけ」。「りんご, みかん」のように1マスに複数詰めるのをやめ、行を分けます。 2NF(第2正規形)は「キーの一部だけで決まる項目を追い出す」。単価は商品名だけで決まるのに注文行ごとに繰り返されていたので、商品マスタへ分離します。 3NF(第3正規形)は「キー以外の項目から芋づる式に決まる項目を追い出す」。住所は顧客が決まれば決まる(注文IDを介した間接的な依存)ので、顧客マスタへ分離します。
用語ミニ辞書
- 正規化
- 重複と更新の矛盾を防ぐため、表を関係(依存)に基づいて分割する設計手順。
- 1NF
- 1セル1値。繰り返しグループ(1マスに複数値)をなくした状態。
- 2NF
- 1NF かつ、複合キーの「一部」だけで決まる項目(部分関数従属)を分離した状態。
- 3NF
- 2NF かつ、キー以外を経由して決まる項目(推移的関数従属)を分離した状態。
まとめ
正規化は、「1つの事実は1か所だけに書く」を実現するために表を切り分ける作業です。重複が消えれば、単価や住所を直すときに1か所直すだけで済み、矛盾したデータが生まれません。図1のステップを行き来して、色つきの重複セルがどのステップで消えるかを目で追ってみてください。実務では速度のためにあえて重複を残す(非正規化)こともありますが、まずは「なぜ分けるのか」を掴むのが先です。