メインコンテンツへスキップ

VillageSQL is a drop-in replacement for MySQL with extensions.

All examples on this page work on VillageSQL. Install Now →
CROSS JOIN は、一方のテーブルのすべての行をもう一方のテーブルのすべての行と 組み合わせます。何も一致させないため、ON 条件は書きません。すべての組み合わせ が欲しいときに求める結合であり、ON 句を書き忘れたときに事故として得る結合でも あります。 始める前に mysql -u root -p sakila でクライアントを開いてください。

CROSS JOIN の仕組み

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

例

  1. すべての組み合わせ

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

  1. カンマは古い書き方

同じ 12 行です。FROM 内の 2 つのテーブルの間のカンマはクロス結合です。古い SQL で出会うことになり、多くの場合、一致条件は下の WHERE にあります。これは 動作しますが、どの種類の結合を読んでいるのかを隠してしまいます。 カンマは JOIN より優先順位が低いため、ON 句はカンマの反対側にあるテーブルに 届きません。この 2 つの書き方は実際のクエリで一緒に現れることがあり、そのとき うまくいかないのがこれです。
クロス結合を意図するときは CROSS JOIN と書き、1 つのクエリでは 1 つの書き方に 統一してください。 キーワードもこのルールを強制しません。MySQL は CROSS JOIN に付いた ON 句を 受け入れ、INNER JOIN として振る舞うため、クエリ内の単語は、得られた結合の証拠 にはなりません。
6,000 ではなく 1,000 です。すべての映画が自分の言語と一致しました。結合が何を するのかを知るには、キーワードではなく ON 句を読んでください。

数はすぐに大きくなる

12 行は無害です。普段クエリするテーブルに対する同じ操作はそうではありません。
1,000 本の映画かける 6 つの言語は 6,000 行で、各映画が 6 つの言語すべてを持つ ことになります。10,000 行のテーブル 2 つをクロスすると答えは 1 億行になり、 一瞬で終わるはずだったクエリが、誰かが止めるまで走り続けるのはこうしてです。 MySQL は ON 句のない INNER JOIN を受け入れ、クロス結合として扱います。そのため、 結合が不自然に切りの良い、不自然に大きな数を返したとき、最初に確認すべきは ON の欠落です。INNER JOIN のレッスンでその事故を 示します。

まとめ

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

関連項目