> ## 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 の CROSS JOIN

> MySQL の CROSS JOIN が一方のテーブルのすべての行をもう一方のすべての行と組み合わせる仕組み、それが生成する行数、および意図したものと事故を見分ける方法。

> [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 →

`CROSS JOIN` は、一方のテーブルのすべての行をもう一方のテーブルのすべての行と
組み合わせます。何も一致させないため、`ON` 条件は書きません。すべての組み合わせ
が欲しいときに求める結合であり、`ON` 句を書き忘れたときに事故として得る結合でも
あります。

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

## CROSS JOIN の仕組み

```sql theme={null}
SELECT COLUMN_LIST
FROM FIRST_TABLE
CROSS JOIN SECOND_TABLE;
```

`COLUMN_LIST` を必要な列に、`FIRST_TABLE` と `SECOND_TABLE` を組み合わせる
テーブルに置き換えます。結果は可能なすべての組み合わせについて 1 行を持つため、
そのサイズは 1 つ目のテーブルの行数に 2 つ目の行数を掛けたものです。6 行と 2 行を
クロスすると 12 行になります。

## 例

### すべての組み合わせ

Sakila には 6 つの言語と 2 つの店舗があります。

```sql theme={null}
SELECT l.name, s.store_id
FROM language AS l
CROSS JOIN store AS s
ORDER BY l.name, s.store_id;
```

```text theme={null}
+----------+----------+
| name     | store_id |
+----------+----------+
| English  |        1 |
| English  |        2 |
| French   |        1 |
| French   |        2 |
| German   |        1 |
| German   |        2 |
| Italian  |        1 |
| Italian  |        2 |
| Japanese |        1 |
| Japanese |        2 |
| Mandarin |        1 |
| Mandarin |        2 |
+----------+----------+
12 rows in set (0.00 sec)
```

すべての言語が店舗ごとに 1 回現れます。ここには、店舗がその言語の映画を在庫して
いるという意味は何もありません。行は組み合わせであって、データについての事実では
ないのです。それがこのクエリの要点です。何かが起きたかどうかにかかわらず
すべての組み合わせについて 1 行が欲しいとき、このような格子が出発点の形に
なります。

### カンマは古い書き方

```sql theme={null}
SELECT l.name, s.store_id
FROM language AS l, store AS s
ORDER BY l.name, s.store_id;
```

```text theme={null}
+----------+----------+
| name     | store_id |
+----------+----------+
| English  |        1 |
| English  |        2 |
| French   |        1 |
| French   |        2 |
| German   |        1 |
| German   |        2 |
| Italian  |        1 |
| Italian  |        2 |
| Japanese |        1 |
| Japanese |        2 |
| Mandarin |        1 |
| Mandarin |        2 |
+----------+----------+
12 rows in set (0.00 sec)
```

同じ 12 行です。`FROM` 内の 2 つのテーブルの間のカンマはクロス結合です。古い
SQL で出会うことになり、多くの場合、一致条件は下の `WHERE` にあります。これは
動作しますが、どの種類の結合を読んでいるのかを隠してしまいます。

カンマは `JOIN` より優先順位が低いため、`ON` 句はカンマの反対側にあるテーブルに
届きません。この 2 つの書き方は実際のクエリで一緒に現れることがあり、そのとき
うまくいかないのがこれです。

```sql theme={null}
SELECT COUNT(*) FROM film f, language l JOIN store s ON s.store_id = f.language_id;
```

```text theme={null}
ERROR 1054 (42S22): Unknown column 'f.language_id' in 'on clause'
```

クロス結合を意図するときは `CROSS JOIN` と書き、1 つのクエリでは 1 つの書き方に
統一してください。

キーワードもこのルールを強制しません。MySQL は `CROSS JOIN` に付いた `ON` 句を
受け入れ、`INNER JOIN` として振る舞うため、クエリ内の単語は、得られた結合の証拠
にはなりません。

```sql theme={null}
SELECT COUNT(*) AS rows_returned
FROM film AS f CROSS JOIN language AS l ON f.language_id = l.language_id;
```

```text theme={null}
+---------------+
| rows_returned |
+---------------+
|          1000 |
+---------------+
1 row in set (0.00 sec)
```

6,000 ではなく 1,000 です。すべての映画が自分の言語と一致しました。結合が何を
するのかを知るには、キーワードではなく `ON` 句を読んでください。

## 数はすぐに大きくなる

12 行は無害です。普段クエリするテーブルに対する同じ操作はそうではありません。

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

```text theme={null}
+-----------------------------+----------+
| title                       | name     |
+-----------------------------+----------+
| ACADEMY DINOSAUR            | English  |
| ACADEMY DINOSAUR            | French   |
| ACADEMY DINOSAUR            | German   |
...
+-----------------------------+----------+
6000 rows in set (0.01 sec)
```

1,000 本の映画かける 6 つの言語は 6,000 行で、各映画が 6 つの言語すべてを持つ
ことになります。10,000 行のテーブル 2 つをクロスすると答えは 1 億行になり、
一瞬で終わるはずだったクエリが、誰かが止めるまで走り続けるのはこうしてです。

MySQL は `ON` 句のない `INNER JOIN` を受け入れ、クロス結合として扱います。そのため、
結合が不自然に切りの良い、不自然に大きな数を返したとき、最初に確認すべきは
`ON` の欠落です。[INNER JOIN](https://villagesql.com/docs/ja/tutorial/inner-join.md) のレッスンでその事故を
示します。

## まとめ

* 一方のテーブルのすべての行をもう一方のすべての行と組み合わせるには `CROSS JOIN` を使います。
* 何も一致させないため、`ON` 句は書きません。
* MySQL は `CROSS JOIN ... ON` をそれでも受け入れ、内部結合として扱うと考えてください。
* 実行する前に、2 つの行数を掛けてサイズを知っておきます。
* `FROM` 内のテーブル間のカンマはクロス結合と読み、1 つのクエリでは 1 つの書き方に統一します。
* 結合が切りの良い大きな行数を返したら、`ON` の欠落を疑います。

## 関連項目

* [結合の仕組み](https://villagesql.com/docs/ja/tutorial/joins.md) — 他の種類の中でのこの結合の位置
* [INNER JOIN](https://villagesql.com/docs/ja/tutorial/inner-join.md) — 代わりに行を一致させる結合
* [テーブルエイリアス](https://villagesql.com/docs/ja/tutorial/table-aliases.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.