SQLのJOINの種類を徹底解説!複数テーブルの結合をマスターする

[PR]

プログラミング

データベースで複数テーブルを結合する操作はアプリや分析で必須です。特に「SQL JOIN 種類」を検索する人は、どのJOINがどんな結果を返すのか、使いどころはどこかを知りたいと考えています。この記事ではINNER、LEFT、RIGHT、FULL、CROSS、SELFなど多くのJOINの種類を例とともに詳しく解説します。順を追って学べば、JOINの使い分けが明確になり、クエリの精度と可読性がぐっと上がります。

目次

SQL JOIN 種類とは何か

複数のテーブルから条件に合致するデータを一つの結果にまとめる操作をJOINと呼びます。JOIN 種類には多数あり、どの種類を選ぶかで取得データが大きく変わるため、正しく理解することが重要です。ここでは代表的なJOIN 種類とその違いを整理します。

JOIN 種類を理解することで、無駄なデータを取得したり、期待と異なる結果が返ったりするバグやパフォーマンス問題を減らせます。SQLが扱えるJOIN 種類をひと通り把握し、いつどれを使うかの判断基準を持てるようになります。

JOINとは基本の概念

JOINは2つ以上のテーブルを、共通する列(キー)を通じて結合し、条件(ON句など)が一致する行を組み合わせる操作です。SQLの標準仕様で定義されているJOIN 種類により、「どの行を残すか」「どの行にNULLを許すか」が決まります。これが理解できると、JOIN 種類の差異が感覚的に分かるようになります。

また、JOIN 種類はデータベース製品によってサポート状況が異なります。たとえばFULL OUTER JOINをサポートしないDBではLEFT JOINとRIGHT JOINのUNIONで代替することが一般的になっています。

JOIN 種類のリスト概要

主要なJOIN 種類には以下があります。代表的なものだけでなく、自己結合(Self JOIN)なども含まれます。

  • INNER JOIN(内側結合)
  • LEFT OUTER JOIN(左外部結合)
  • RIGHT OUTER JOIN(右外部結合)
  • FULL OUTER JOIN(完全外部結合)
  • CROSS JOIN(直積結合)
  • SELF JOIN(自己結合)

主要なSQL JOIN 種類とその挙動の比較

まずINNER、LEFT、RIGHT、FULLなど主要なJOIN 種類を比較して、それぞれの特徴を明確にします。これによりどの状況でどのJOIN を使えばいいかが分かるようになります。

INNER JOINの特徴と使いどころ

INNER JOINは2つのテーブル双方で条件が一致する行のみを返します。条件に合致しない行は全て除外されるため、最も「共通部分」に焦点を当てた取得方法です。デフォルトでJOINと書いた場合、INNER JOINとして扱われるデータベースが多いです。

使いどころとしては、売上がある顧客だけを取得したいときや、部門と従業員のうち所属が明示されている組み合わせだけが必要な場合などが典型です。条件にNULLが含まれる場合、その行は無視されるという点を理解しておく必要があります。

LEFT OUTER JOIN(LEFT JOIN)の特徴と使いどころ

LEFT JOINは左側(FROM句に書いたテーブル)にある全行を保持し、右側と一致する行があれば結合し、一致しない場合は右側の列にNULLを埋めて返します。主テーブルを中心にして、関連情報があれば付け加えたい場面で重宝します。

たとえば顧客テーブルを主に、注文がない顧客も含めたい場合や、社員がまだ部署に所属していないケースを含めて一覧にしたい場合などです。LEFT JOINの後にWHEREで右側の列を条件にするとINNER JOINと同じ結果になるため、ON句での条件指定が大事です。

RIGHT OUTER JOIN(RIGHT JOIN)の特徴と使いどころ

RIGHT JOINはRIGHT側のテーブル全行を保持し、左側との一致があれば結合し、一致しない場合左側の列にNULLを埋めます。LEFT JOINを逆にしたような動きになりますが、可読性や仕様の観点であまり使われないことが多いです。

使うケースとしてはRIGHT側テーブルを主として保ちたいとき、またはデータ統合などで右側のデータが完全な基準となっているときです。ただしLEFT JOINで実現可能な場合はLEFT JOINを使うほうが一般的です。

FULL OUTER JOINの特徴と使いどころ

FULL OUTER JOINはLEFT JOINとRIGHT JOINを合体させたものです。両方のテーブルの全行を保持し、一致しない行には対応側の列をNULLで埋めて返します。両方のテーブルのギャップを確認したいときなどに役立ちます。

たとえば顧客リストと請求リストの両方に存在しない顧客・注文を調べたいときに使われます。ただしサポートしていないDBもあるため、代替手法としてLEFT JOINとRIGHT JOINのUNIONを使うことがあります。

CROSS JOINの特徴と使いどころ

CROSS JOINはテーブルAの各行とテーブルBの各行を全て組み合わせて返す直積です。結合条件がない状態で使われるため、結果の行数が急増する可能性があります。テスト用データ生成や組み合わせリスト作成など限定された用途で使われます。

使いどころは、色とサイズの組み合わせをすべて列挙したい場合や、日付や時間の全組み合わせを対象とするマトリックス的なレポート作成などです。誤ってON句を省略してCROSS JOIN相当の結果になってしまうというバグの原因にもなりやすいので注意が必要です。

拡張的なSQL JOIN 種類と応用パターン

主要なJOIN 種類のほか、実践で便利な応用パターンや拡張JOINSを知ることで、より高度なクエリ設計ができます。ここではSELF JOINや自然結合、ONとUSINGの使い分け、多テーブルJOINなどを扱います。

SELF JOIN(自己結合)とは

SELF JOINはテーブル自身と結合するパターンです。従業員とその上司、親カテゴリと子カテゴリなど、同一テーブルの中で行間の関係性を取得したいときに使われます。エイリアスを活用して区別して書くことが一般的です。

例えば社員テーブルにmanager_id列があり、同じテーブル内のidと結びつけて上司の名前を取得するケースがあります。SELF JOINはどのJOIN 種類(INNER, LEFTなど)でも使える応用形態です。

自然結合(NATURAL JOIN)の意味と注意点

NATURAL JOINは同じ名前とデータ型の列を自動で共通キーとして使い、重複する共通列を一つにして結果を返すINNER JOINの一種です。コードが短く書けるため便利ですが、どの列が共通になるか把握しておかないと予期しない結果となる可能性があります。

適切な場合は自然結合でコードを簡潔にできますが、明示的なON句を使う方が可読性と保守性が高くなります。自然結合を使うときは共通列の名前や型に注意を払うことが重要です。

ON句とUSING句の使い分け

JOIN時に結合条件を指定する方法としてON句とUSING句があります。多くのデータベースでON句が一般的で、複雑な条件や列名が異なる場合に自由度が高いです。USING句は同じ列名で共通キーを指定する際に簡潔です。

ただしUSING句は全てのDBでサポートされておらず、ON句の方が汎用性があります。NULL扱いや重複列の扱いにも差が出るため、コード規約としてどちらを使うかプロジェクトで統一するのが望ましいです。

複数テーブル結合とJOINの順序の影響

3テーブル以上のJOINを使うとき、JOINする順序や結合条件の書き方によって結果の可読性やパフォーマンスに大きな影響があります。SQLオプティマイザは順序を最適化することが多いですが、人が読むときは順序とエイリアスで構造を明確にすることが重要です。

特にOUTER JOINを含む複数結合では、ON句のWHERE句への条件追加が意図しない結果を招くことがあります。外部結合でNULLが入る可能性を考慮して条件をONに書くか、結合後のフィルタと意図を整理してから書くようにします。

SQL JOIN 種類ごとの構文と例

ここでは代表的なJOIN 種類それぞれでSQL構文と実際にどう動くか例を使って解説します。理解を深めるために具体的なテーブルとサンプルクエリを使います。

INNER JOINの構文と例

構文は以下のようになります。FROM句でテーブルA、INNER JOINでテーブルB、ON句で結合条件を指定します。これにより両方に存在する条件にマッチする行のみ結果に含めます。

例として顧客テーブルと注文テーブルを使い、注文が存在する顧客の名前と注文IDを取得するクエリ:

SELECT c.customer_name, o.order_id FROM customers c INNER JOIN orders o ON c.customer_id = o.customer_id;

この結果には、注文がない顧客は含まれません。顧客テーブルに存在しない注文も除外されます。

LEFT JOIN(LEFT OUTER JOIN)の構文と例

LEFT JOINの構文では、左側のテーブルにある全行を返します。一致しない場合は右側の列にNULLが入ります。使いどころは主テーブルを優先したいときです。

例:顧客一覧を出して、注文があれば注文情報を付けたいが、注文がない顧客も表示したい場合:

SELECT c.customer_name, o.order_id, o.amount FROM customers c LEFT JOIN orders o ON c.customer_id = o.customer_id;

この場合、注文が一つもない顧客にはorder_idとamountがNULLとなる行が返されます。

RIGHT JOIN(RIGHT OUTER JOIN)の構文と例

RIGHT JOINでは右側のテーブルを基準に全行を保持します。左側との一致がない場合、左側の列にNULLが入り、右側の情報は残ります。

例えば、注文テーブルを主線とし、顧客情報がない注文も含めたいときの例:

SELECT c.customer_name, o.order_id, o.amount FROM customers c RIGHT JOIN orders o ON c.customer_id = o.customer_id;

このクエリでは、顧客テーブルに対応する顧客が登録されていなかったとしても、注文レコードは取得され、顧客名列にNULLが入ります。

FULL OUTER JOINの構文と例

FULL OUTER JOINは両方のテーブルの全行を取得し、一致しない場合は対応する列にNULLを埋めます。両テーブルの差分を含めたいときに使われます。

例:顧客テーブルと注文テーブルから、どちらかにしかないデータも含めて一覧を取得したい場合:

SELECT c.customer_name, o.order_id, o.amount FROM customers c FULL OUTER JOIN orders o ON c.customer_id = o.customer_id;

このクエリでは顧客のみ・注文のみのレコードも含まれます。サポートされていないDBではLEFT JOINとRIGHT JOINをUNIONする方法で代替されます。

CROSS JOINの構文と例

CROSS JOINは条件なしに全ての組み合わせを生成します。構文は簡単ですが、誤って使うと非常に大きな結果セットになることに注意です。

例:色テーブルとサイズテーブルからあらゆる組み合わせを作るレポートが必要な場合:

SELECT color.color_name, size.size_name FROM colors color CROSS JOIN sizes size;

このクエリでは色の数×サイズの数だけの行が返ります。

SELF JOINの構文と例

SELF JOINは同じテーブル同士をエイリアスを使って結合するパターンで、階層構造やリンク関係の取得に使われます。

例:従業員テーブルでmanager_id列を持つものがあり、従業員とその上司の名前を同じテーブルから取得する場合:

SELECT e.employee_name AS employee, m.employee_name AS manager FROM employees e LEFT JOIN employees m ON e.manager_id = m.employee_id;

この例では、上司が存在しない従業員はmanager列がNULLになります。

SQL JOIN 種類のパフォーマンスと使い分けのポイント

JOIN 種類を選ぶ際には正しい挙動だけでなく、パフォーマンスや実行コストも知っておくと良いです。JOIN 種類によって内部で使われるアルゴリズムやインデックスの効き方が異なりますので、使い分けの基準を押さえましょう。

インデックスの活用とキーの選定

JOIN のON句に指定するカラムにインデックスが張られていると、結合処理が高速になります。特にINNER JOIN や LEFT JOIN は主従関係で頻繁に使われるため、外部キーや対応するカラムをインデックス化することが効果的です。

適切にインデックスがない場合、全行スキャン(フルテーブルスキャン)が発生し、結果セットが膨れたり処理時間が長くなったりします。JOIN前に統計情報が最新であることも重要です。

JOIN の結果行数と多重結合の影響

CROSS JOIN や多対多の関係を含むINNER JOIN などでは、予期せぬ多重行が生成されることがあります。JOIN の結果が思った以上に多くなる原因を把握するためにも、テーブルの関係性(1対1、1対多、多対多)を理解しておくことが必要です。

また複数テーブルをJOIN するクエリでは、順序や結合条件、外部結合がどのテーブルにかかるかが結果に影響する場合があります。WHERE句をJOIN後に書くとNULL行が除かれてしまうこともあります。

データベース差異とサポート状況

代表的なDB製品ではINNER, LEFT, RIGHT, CROSSはほぼサポートされていますが、FULL OUTER JOINはサポート外のものもあります。そういったDBではLEFTとRIGHTのUNIONで代替されます。

自然結合やUSING句のサポートも製品により異なります。可読性や保守性を重視するなら、標準的な構文(ON句)で明示的に書くほうが問題に遭いにくいです。

実践でよくある誤りと検証方法

JOIN 種類を誤って使ったり、期待と異なる結果が返るパターンは意外と多いです。ここでは代表的なミス例と、それを防ぐための検証方法について解説します。

条件をWHERE句に書いて外部結合の意味を失うケース

LEFT JOIN や RIGHT JOIN の後でWHERE句に結合先のテーブルの列を条件として書くと、NULLが入っていた行がすべて除かれてしまい、実質的にINNER JOIN と同じ結果になることがあります。これにより主テーブルに存在する行が意図せず除外されることがあります。

防ぐためには、外部結合のNULL許容部分の条件をON句に含めるか、条件付きLEFT JOIN を使うようにすることがポイントです。結果の正当性をテストデータで確認することも有効です。

CROSS JOIN の誤用による急激な行数の増加

ON句を忘れた状態でJOINを使うと、意図せずCROSS JOIN と同じ直積が生成されることがあります。テーブルのサイズが大きいと結果が爆発的に増えてしまい、メモリや実行時間に大きな影響を与えます。

JOINを記述する際は必ずON句またはUSING句で結合条件を指定する癖をつけ、クエリ実行前にどれくらいの行数が返りそうかを想像しておくことが望ましいです。

NULL値の扱いに関する落とし穴

JOIN条件または結合後にNULLが関わると、期待したマッチングが行われないことがあります。例えばINNER JOINの場合、どちらか側にNULLがあるとその行は除外され、LEFT JOINではNULL側がNULLのまま残ります。

NULLとの比較ではIS NULLやCOALESCEを使うなど明示的な処理を加えることで想定外の除外を防げます。データベース設計時からNULLのある列をJOINキーにするかどうかを検討すると良いです。

SQL JOIN 種類の選択フローと実践例

JOIN 種類を迷わずに選べるように、条件に応じた選択フローと実践例を示します。どのJOIN 種類が適しているか判断する基準になります。

どちらのテーブルを「基準」にするかの判断

どちらのテーブルの行をすべて残したいかをまず考えます。主テーブル(例えば顧客テーブルなど)を基準にするならLEFT JOINを使い、逆ならRIGHT JOINを使います。両方残したいならFULL OUTER JOINが候補になります。

またSELF JOINではテーブル内で上司・部下など階層構造の基準が内部で決まります。結合する方向性(直属上司か一段階上かなど)を明確にしておくと書きやすくなります。

ユースケース別のJOIN種別選択例

以下は具体的なビジネス要件に応じたJOIN 種類の選択例です。クエリ設計時に参考になるモデルです。

  • すべての顧客とその注文をリストアップしたい:LEFT JOIN
  • 注文が存在する顧客だけのレポートが必要:INNER JOIN
  • 請求書にだけデータがあり、顧客データが欠落している可能性を含めたい:RIGHT JOINまたはFULL OUTER JOIN
  • 異なる要素(色・サイズ等)の全組み合わせを試算したい:CROSS JOIN
  • 社員とその上司の関係を一つのテーブルから取得したい:SELF JOIN

選択フローまとめ

以下のフローチャートのように基準テーブルと目的からJOIN 種類を決めると迷いが少なくなります。

質問 YESの場合 NOの場合
片方のテーブルの全行が必要か? LEFTまたはRIGHTを検討 INNERが候補
両方のテーブルの全行が必要か? FULL OUTER JOINを使う 条件でINNERか外部結合
組み合わせをすべて列挙したいか? CROSS JOINを使う その他を検討

SQL JOIN 種類の実際のデータベースでのサポート状況

SQL JOIN 種類が標準構文でも、データベースエンジンによってサポート状況が異なる場合があります。実際の環境で使えるかを確認するのが重要です。

FULL OUTER JOINの非対応環境があるケース

MySQLなど一部のデータベースではFULL OUTER JOINをネイティブにサポートしていないことがあります。その際にはLEFT JOINとRIGHT JOINを組み合わせたUNIONで同様の結果を得ることが一般的な代替手段です。

代替の例として、LEFT JOIN したものと RIGHT JOIN したものをUNIONし、重複を取り除くようにすると、似たような出力が得られます。ただしパフォーマンスが落ちる可能性があるため注意が必要です。

自然結合とUSING句の対応状況

NATURAL JOINやUSING句は便利ですが、すべてのデータベースで文法が完全にサポートされているわけではありません。特に列名が自動で共通列として扱われる部分が異なることがあるため、環境によってテストが必要です。

ON句を使った明示的な結合条件を書くことで、どのDBでも同じ結果が得やすくなります。チーム方針として構文スタイルを統一することが保守性を高めます。

パフォーマンス上の注意点(実行計画とリソース)

大規模データでJOINを多用するとディスクIOやメモリ使用量が急増することがあります。特にCROSS JOINはデータ量の掛け算になるため注意が必要です。統計情報やインデックスが古いと最適な実行計画が選ばれない原因になります。

実行計画(EXPLAIN等)でJOINの順序、アクセス方法(ネストループかハッシュかマージか)を確認し、必要ならサブクエリやインデックス追加、JOIN順序を工夫するようにします。

まとめ

SQL JOIN 種類の理解とは、どのJOINを使うかで得られるデータの内容が大きく変わるということです。INNER, LEFT, RIGHT, FULL, CROSS, SELF といった種類の動作を把握することで、クエリの結果が期待通りか確認できるようになります。JOINの前提となるテーブルの関係性、NULLの扱い、サポートされている構文をまず頭に入れておきましょう。

またパフォーマンス面でも、インデックスや実行計画、JOINの順序や条件の書き方が重要です。誤ったJOINの使い方はバグや遅い処理の原因になります。実践的な要件に応じてどのJOIN 種類を選べばよいかの判断フローを持つことが、プロのクエリ設計には不可欠です。

関連記事

特集記事

コメント

この記事へのトラックバックはありません。

TOP
CLOSE