0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

RDB設計思想を理解する「多対多」と「中間テーブル」の意味を整理

Last updated at Posted at 2025-04-06

WebサービスなどでDB設計をするとき、よく適当にテーブルを設計して「このテーブルにもID一覧持たせておけばよくないかな」と考えてしまいがちな人向けに、RDBでなぜ「中間テーブル」を用いるのかを「多対多」をキーワードになるべくまとめます。


情報モデル

以下のようなモデルを例にします:

  • User : ユーザー
  • Post : 投稿記事
  • Tag : タグ
  • PostTag : タグと投稿の関係を管理する中間テーブル

問題起点

「Postについているタグ名を持たせたいならpost テーブルに tag_name からなる列を持たせれば良いじゃん?」と思うことがあります。しかしこれはRDBの設計思想に反します。


ユーケース: Post ID=1 の投稿に付けられたタグを取得したい

例:

SELECT t.id, t.name
FROM PostTag pt
JOIN Tag t ON pt.tag_id = t.id
WHERE pt.post_id = 1;

これにより、Postに繋がる複数のタグをもれなく取得できます。


なぜ中間テーブルを作るの?

1. 多対多を表現するには、テーブルを分ける必要がある

1つのPostに複数のTag、そのTagは別のPostにも使われる。
これが「多対多 (N:N)」の構造。

RDBでは、多対多を表現するときに「中間テーブル」を作ります:

Post (1) ---< PostTag >--- (1) Tag

2. 1つの行に複数値を持たせない (1NF)

NG例:

post_id tag_names
1 "アウトドア,一人OK,自然"
  • 検索しづらい
  • 表示ゆれが起きやすい
  • 更新が難しい

3. Tagはマスタデータ

Tagは名前や色情報を含んだ「定義情報」として別て管理するのがメンテナンス性が高い。

  • Tagの名前を変更するところは1ーexecuteで手忙で管理できる
  • Post側のデータは変える必要がない

4. JOINすれば欲しい情報はすぐに取れる

タグ名が欲しければ、JOINするだけ。


まとめ

項目 理由
中間テーブルを作る 多対多を表現するため
Tag名を持たせない Tagテーブルから取れば良い
同じTagを複数使い回せる データ重複を避けるため
変更性が高い 1か手を入れるだけで全体に反映

後記

今回のメモは、自分でDBを設計する際に「なぜ中間テーブルを作るのか」を説明できるようにするための理解の基礎を整理したものです。
もっと難しいテーマ(グループ化や縦方スケーリング)を考える前に、この基本を理解していることが重要です。

全体のテーブル設計の流れやユーケースの定義、ER図化なども別記事で何回かに分けて書く予定です。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?