一覧へ

リレーショナルデータベース — JOINと正規化

なぜテーブルを分割するのか、JOINでどのように結合するのか、正規化がなぜ必要なのか、実際の例で理解します。

中級
|
8
|
検証済み (2026-07)
進捗0/55 (0%)

リレーショナルデータベース — JOINと正規化

このトピックを終えると

テーブルを分割する理由を説明でき、JOINを使ってデータを結合するSQLを作成できるようになります。


1つのテーブルでは不十分

オンラインショッピングを作成するとしましょう。すべての注文情報を1つのテーブルに保存するとどうなるでしょうか?

text
orders (すべての情報を1つのテーブルに):
+----+--------+-------+----------+--------+
| id | 顧客名 | メール | 商品名   | 価格   |
+----+--------+-------+----------+--------+
|  1 | 김훈   | h@ex  | ノートPC | 150万  |
|  2 | 김훈   | h@ex  | マウス   |   5万  |
|  3 | 이수   | s@ex  | キーボード |  10万  |
+----+--------+-------+----------+--------+

問題点はわかりますか?

  • 重複: "김훈"と"h@ex"が注文するたびに繰り返されます。
  • 修正のリスク: 김훈がメールアドレスを変更した場合、すべての行を修正する必要があります。1つでも見落とすと不整合が発生します。
  • 削除のリスク: 김훈のすべての注文を削除すると、顧客情報自体が消えてしまいます。

テーブルの分割 — 正規化の基本

解決策は、関連するデータを別のテーブルに分割することです。

text
usersテーブル:                  ordersテーブル:
+----+--------+-------+         +----+---------+----------+--------+
| id | name   | email |         | id | user_id | product  | price  |
+----+--------+-------+         +----+---------+----------+--------+
|  1 | 김훈   | h@ex  |         |  1 |    1    | ノートPC | 150万  |
|  2 | 이수   | s@ex  |         |  2 |    1    | マウス   |   5万  |
+----+--------+-------+         |  3 |    2    | キーボード |  10万  |
                                 +----+---------+----------+--------+

orders.user_idusers.idを指します。これが外部キー(Foreign Key) — 2つのテーブルを接続するリンクです。

このように重複を削除し、テーブルを分割するプロセスを**正規化(Normalization)**と呼びます。


JOIN — 分割されたテーブルを結合する

テーブルを分割したので、再度結合して表示する方法が必要です。それがJOINです。

sql
-- 注文リストに顧客名を付加して照会
SELECT users.name, orders.product, orders.price
FROM orders
JOIN users ON orders.user_id = users.id;

結果:

text
+--------+----------+--------+
| name   | product  | price  |
+--------+----------+--------+
| 김훈   | ノートPC | 150万  |
| 김훈   | マウス   |   5万  |
| 이수   | キーボード |  10万  |
+--------+----------+--------+

JOIN ... ONの後に、どの列を基準にマッチングするかを指定します。orders.user_id = users.id — 注文のuser_idとユーザーのidが同じ行同士を結合します。


JOINの種類

sql
-- INNER JOIN: 両方にマッチする行のみ(デフォルト)
SELECT * FROM orders JOIN users ON orders.user_id = users.id;

-- LEFT JOIN: 左側のテーブルはすべて、右側はマッチするもののみ
-- 注文がない顧客も含む
SELECT users.name, orders.product
FROM users
LEFT JOIN orders ON users.id = orders.user_id;

-- 結果: 注文がない顧客はproductがNULLで表示される
JOINの種類説明
INNER JOIN両方に存在するデータのみ
LEFT JOIN左側すべて + 右側は存在すれば結合
RIGHT JOIN右側すべて + 左側は存在すれば結合

実務では、INNER JOINLEFT JOINを最もよく使用します。


正規化 — なぜ分割するのか

正規化の基本的な原則は単純です: 1つの事実は1つの場所にのみ保存する。

正規化前正規化後効果
顧客名が注文ごとに繰り返されるusersテーブルに1回のみ重複の削除
メールアドレスの変更時にN行修正1行のみ修正一貫性の保証
注文の削除時に顧客が消滅顧客が独立して存在するデータの保存

正規化は「常に良い」わけではありません。テーブルが細かく分割されすぎると、JOINが複雑になり、パフォーマンスが低下する可能性があります。実務では、パフォーマンスのために意図的に重複を許可することもあります(非正規化)。しかし、基本は正規化です。


💬 質問・コメント

0件のコメント

ログインせずに投稿できます。ゲスト投稿は投稿者自身で編集・削除できません。

0/2000

読み込み中...