テーブル構造を考える③（具体例）

[①の記事](https://qiita.com/ruuuuu/items/4c68977accfa80ff9920)と[②の記事](https://qiita.com/ruuuuu/items/52f9653b159d41f301c8)で理論的なテーブル構造について学びました。
本記事では、具体例を用いて第三正規化まで行ってみましょう。

## 対象のテーブル
本記事では、以下のような例を考えます。
ブログの記事があり、それ1つに対して、ユーザは一回だけ"いいね"ができます。これをテーブルに表すと以下のようになります。

<table>
<tr>
    <th>ブログID</th>
    <th>タイトル</th>
    <th>本文</th>
    <th>作成日</th>
    <th>いいねユーザ名</th>
    <th>ユーザメールアドレス</th>
    <th>いいねした日付</th>
</tr>
<tr>
    <td rowspan="2">1</td>
    <td rowspan="2">タイトル1</td>
    <td rowspan="2">本文1</td>
    <td rowspan="2">2024/10/01</td>
    <td>ユーザA</td>
    <td>a@example.com</td>
    <td>2024/10/01</td>
</tr>
<tr>
    <td>ユーザB</td>
    <td>b@example.com</td>
    <td>2024/10/02</td>
</tr>
<tr>
    <td>2</td>
    <td>タイトル2</td>
    <td>本文2</td>
    <td>2024/10/02</td>
    <td>ユーザC</td>
    <td>c@example.com</td>
    <td>2024/10/02</td>
</tr>
<tr>
    <td rowspan="3">3</td>
    <td rowspan="3">タイトル3</td>
    <td rowspan="3">本文3</td>
    <td rowspan="3">2024/10/04</td>
    <td>ユーザA</td>
    <td>a@example.com</td>
    <td>2024/10/04</td>
</tr>
<tr>
    <td>ユーザB</td>
    <td>b@example.com</td>
    <td>2024/10/04</td>
</tr>
<tr>
    <td>ユーザC</td>
    <td>c@example.com</td>
    <td>2024/10/05</td>
</tr>
</table>

以上のテーブルに対して、第三正規化まで考えます。

## 非正規形
非正規形とは、1つのセルに複数の値が含まれている状態のことです。

<table>
<tr>
    <th>ブログID</th>
    <th>タイトル</th>
    <th>本文</th>
    <th>作成日</th>
    <th>いいねユーザ名</th>
    <th>ユーザメールアドレス</th>
    <th>いいねした日付</th>
</tr>
<tr>
    <td rowspan="2">1</td>
    <td rowspan="2">タイトル1</td>
    <td rowspan="2">本文1</td>
    <td rowspan="2">2024/10/01</td>
    <td>ユーザA</td>
    <td>a@example.com</td>
    <td>2024/10/01</td>
</tr>
<tr>
    <td>ユーザB</td>
    <td>b@example.com</td>
    <td>2024/10/02</td>
</tr>
<tr>
    <td>2</td>
    <td>タイトル2</td>
    <td>本文2</td>
    <td>2024/10/02</td>
    <td>ユーザC</td>
    <td>c@example.com</td>
    <td>2024/10/02</td>
</tr>
<tr>
    <td rowspan="3">3</td>
    <td rowspan="3">タイトル3</td>
    <td rowspan="3">本文3</td>
    <td rowspan="3">2024/10/04</td>
    <td>ユーザA</td>
    <td>a@example.com</td>
    <td>2024/10/04</td>
</tr>
<tr>
    <td>ユーザB</td>
    <td>b@example.com</td>
    <td>2024/10/04</td>
</tr>
<tr>
    <td>ユーザC</td>
    <td>c@example.com</td>
    <td>2024/10/05</td>
</tr>
</table>

* **問題点**：「いいね」したユーザが1つのブログ記事のデータに対して何度も繰り返し現れています。

## 第一正規形
第一正規形は、データを一行で表し、各セルに1つの値のみを持たせる状態です。

**第一正規形のテーブル**
| ブログID | タイトル   | 本文   | 作成日      | いいねユーザ名 | ユーザメールアドレス | いいねした日付 |
|----------|------------|--------|-------------|----------------|----------------------|----------------|
| 1        | タイトル1 | 本文1  | 2024/10/01  | ユーザA        | a@example.com        | 2024/10/01     |
| 1        | タイトル1 | 本文1  | 2024/10/01  | ユーザB        | b@example.com        | 2024/10/02     |
| 2        | タイトル2 | 本文2  | 2024/10/02  | ユーザC        | c@example.com        | 2024/10/02     |
| 3        | タイトル3 | 本文3  | 2024/10/04  | ユーザA        | a@example.com        | 2024/10/04     |
| 3        | タイトル3 | 本文3  | 2024/10/04  | ユーザB        | b@example.com        | 2024/10/04     |
| 3        | タイトル3 | 本文3  | 2024/10/04  | ユーザC        | c@example.com        | 2024/10/05     |


* **改善点**：各セルに単一の値が含まれるようになり、データの冗長性が減少しました。

## 第二正規形
第二正規形は、すべての非キーが候補キーに対して完全関数従属の状態です。

ここで、候補キーに対して考えます。候補キーは、データを一意に特定できるカラム（もしくは、カラムの集合）のことです。今回のテーブルだと、単一のキーはどれも重複しているため、候補キーになれません。ペアで考えてみると、{ブログID, いいねユーザ名}が候補キーになっていることが分かります。逆にそれ以外は非キーとなります。

非キーである、タイトル、本文、作成日は、ブログのIDに対して従属であり、ユーザメールアドレスはいいねユーザ名に対して従属です。また、いいねした日付は、ブログIDといいねユーザ名が確定すれば決まる値です。よって、いいねした日付のみ、完全関数従属であり、それ以外は候補キーから値が決定できるわけではないので、分離する必要があります。

**いいねテーブル**
| ブログID | いいねユーザ名 | いいねした日付 |
|----------|----------------|----------------|
| 1        | ユーザA        | 2024/10/01     |
| 1        | ユーザB        | 2024/10/02     |
| 2        | ユーザC        | 2024/10/02     |
| 3        | ユーザA        | 2024/10/04     |
| 3        | ユーザB        | 2024/10/04     |
| 3        | ユーザC        | 2024/10/05     |

**ユーザテーブル**
| ユーザ名 | ユーザメールアドレス   |
|----------------|------------------------|
| ユーザA        | a@example.com          |
| ユーザB        | b@example.com          |
| ユーザC        | c@example.com          |

**ブログテーブル**
| ブログID | タイトル   | 本文   | 作成日      |
|----------|------------|--------|-------------|
| 1        | タイトル1 | 本文1  | 2024/10/01  |
| 2        | タイトル2 | 本文2  | 2024/10/02  |
| 3        | タイトル3 | 本文3  | 2024/10/04  |

これで、第二正規形を満たしていると言えます。

## 第三正規形
第三正規形は、すべての非キーが候補キーに従属している状態のことです。

第二正規形で作成したすべてのテーブルはそのテーブルの主キー（候補キー）に従属しているため、この時点で第三正規形を満たしていると言えます。