> ## Documentation Index
> Fetch the complete documentation index at: https://villagesql.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# MySQL の結合の仕組み

> MySQL でデータが複数のテーブルに分かれている理由、結合がそれを再び 1 つにまとめるために行うこと、そして内部結合と外部結合とクロス結合の違い。

> [card] [VillageSQL is a drop-in replacement for MySQL with extensions.](https://villagesql.com/docs/en/8.4/stable/install-server.md)
>
> All examples on this page work on VillageSQL. Install Now →

ここまでのクエリはすべて 1 つのテーブルを読んできました。実際のデータベースは
情報を多数のテーブルに分散しており、結合はそれらをまたいで読む方法です。この
レッスンでは、結合が何をするのか、そして各種類が何のためにあるのかを説明
します。この後のレッスンでは、各種類を順に取り上げます。

始める前に `mysql -u root -p sakila` でクライアントを開いてください。

## データが分かれている理由

Sakila は各映画の言語を数値として記録しています。

```sql theme={null}
SELECT film_id, title, language_id FROM film ORDER BY film_id LIMIT 3;
```

```text theme={null}
+---------+------------------+-------------+
| film_id | title            | language_id |
+---------+------------------+-------------+
|       1 | ACADEMY DINOSAUR |           1 |
|       2 | ACE GOLDFINGER   |           1 |
|       3 | ADAPTATION HOLES |           1 |
+---------+------------------+-------------+
3 rows in set (0.00 sec)
```

その数値に対応する名前は、専用のテーブルにあります。

```sql theme={null}
SELECT language_id, name FROM language ORDER BY language_id;
```

```text theme={null}
+-------------+----------+
| language_id | name     |
+-------------+----------+
|           1 | English  |
|           2 | Italian  |
|           3 | Japanese |
|           4 | Mandarin |
|           5 | French   |
|           6 | German   |
+-------------+----------+
6 rows in set (0.00 sec)
```

`English` という単語を 1 回保存して 1,000 回それを指すほうが、1,000 回保存する
より場所を取らず、綴りの修正も 1,000 行ではなく 1 行の変更で済みます。その
代償として、タイトルと言語名が欲しいクエリは両方のテーブルを読まなければ
なりません。

## 結合の仕組み

```sql theme={null}
SELECT COLUMN_LIST
FROM LEFT_TABLE
JOIN RIGHT_TABLE ON LEFT_TABLE.COLUMN_NAME = RIGHT_TABLE.COLUMN_NAME;
```

`COLUMN_LIST` を欲しい列に、`LEFT_TABLE` を起点にするテーブルに、
`RIGHT_TABLE` を追加の列を取り出すテーブルに、各 `COLUMN_NAME` をそれぞれの
側で 2 つのテーブルをつなぐ列に置き換えます。

サーバーは左テーブルの各行を取り、`ON` 条件が真になる右テーブルの行を
見つけ、一致ごとに 1 つの結合された行を返します。

## 例

### 数値の代わりに名前を読む

```sql theme={null}
SELECT f.title, l.name
FROM film AS f
JOIN language AS l ON f.language_id = l.language_id
ORDER BY f.title
LIMIT 3;
```

```text theme={null}
+------------------+---------+
| title            | name    |
+------------------+---------+
| ACADEMY DINOSAUR | English |
| ACE GOLDFINGER   | English |
| ADAPTATION HOLES | English |
+------------------+---------+
3 rows in set (0.00 sec)
```

`AS f` と `AS l` はテーブルのエイリアスです。
[次のレッスン](https://villagesql.com/docs/ja/tutorial/table-aliases.md)で扱います。

## 結合の種類は何のためにあるか

種類の違いは 1 点だけです。一致が見つからなかった行がどうなるかです。

| 結合 | 残すもの |
| - | - |
| `INNER JOIN` | 両側で一致が見つかった行だけ |
| `LEFT JOIN` | 左テーブルのすべての行(一致の有無を問わず) |
| `RIGHT JOIN` | 右テーブルのすべての行(一致の有無を問わず) |
| `CROSS JOIN` | 左のすべての行と右のすべての行の組み合わせ |

外部結合が残した一致しない行も、値を持たない列を埋めなければならず、
NULL で埋めます。`LEFT JOIN` の横に [IS NULL](https://villagesql.com/docs/ja/tutorial/is-null.md) がよく現れる
のはそのためです。それが、何にも一致しなかった行を求める方法です。

`CROSS JOIN` は行の突き合わせを行わないので、仲間外れです。すべての組み合わせが
欲しいときに意図的に使うものであり、`ON` 句を書き忘れたときに偶然得られる
ものでもあります。

## キーワードより条件が重要

MySQL では `JOIN`、`INNER JOIN`、`CROSS JOIN` は 1 つのものであり、文法上は
どれにも `ON` 句を付けても付けなくても構いません。つまり、入力したキーワード
が結果を決めるのではありません。`ON` 条件の有無が決めます。あれば一致が
得られ、なければすべての組み合わせが得られます。3 つの語のどれを書いたかは
関係ありません。

サーバーは区別してくれないので、一致を意味するときは `INNER JOIN ... ON` と
書き、すべての組み合わせを意味するときは `ON` なしの `CROSS JOIN` と書いて
ください。そうすればキーワードは、サーバーへの命令ではなく次の読み手への
メモになります。

## まとめ

* 情報はテーブルをまたいで分かれており、1 つのテーブルが id で別のテーブルを指しています。
* それらのテーブルを 1 つのクエリでまたいで読むには結合を使います。
* `ON` 条件は、どの行同士が対応するかのルールと読みます。
* 何にも一致しない行がどうなるべきかで、結合の種類を選びます。
* 外部結合が一致なしで残した行の列には NULL が入ります。

## 関連項目

* [テーブルのエイリアス](https://villagesql.com/docs/ja/tutorial/table-aliases.md)と [INNER JOIN](https://villagesql.com/docs/ja/tutorial/inner-join.md) — 短い名前と、一致だけを残す結合
* [LEFT JOIN](https://villagesql.com/docs/ja/tutorial/left-join.md) と [RIGHT JOIN](https://villagesql.com/docs/ja/tutorial/right-join.md) — 一致しない行を残す結合
* [CROSS JOIN](https://villagesql.com/docs/ja/tutorial/cross-join.md) と[自己結合](https://villagesql.com/docs/ja/tutorial/self-join.md) — すべての組み合わせと、自分自身と結合するテーブル
* [MySQL の JOIN のパフォーマンスとよくある間違い](https://villagesql.com/docs/ja/guides/joins.md) — テーブルが大きくなったときに起きる問題


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.