SQLの結合と副問い合わせを徹底解説!両方を使いこなす実践例付き

データベース操作で欠かせないのが「結合(JOIN)」と「副問い合わせ(サブクエリ)」です。
どちらも複数のテーブルを扱う際に使われる機能ですが、役割や使いどころが異なります。

たとえば、売上データと顧客情報を結びつけたいときには「結合」を使います。
一方で、「特定条件を満たすデータだけを別のテーブルに使いたい」場合は、副問い合わせが活躍します。

この記事では、まず結合と副問い合わせの基本をわかりやすく解説し、その後「結合と副問い合わせを同時に使う」実践的なケースを具体的なSQL例とともに紹介します。
初心者から中級者まで、業務で使える実践知識が身につく内容です。


SQLの結合とは?基本を理解しよう

SQLの「結合(JOIN)」とは、複数のテーブルを共通するキー(列)で結びつけて1つの結果セットとして取得する機能です。

たとえば、次のような2つのテーブルがあるとします。

顧客テーブル(customers)

customer_idnamecity
1田中太郎東京
2鈴木花子大阪
3佐藤健福岡

注文テーブル(orders)

order_idcustomer_idorder_dateamount
10112025-10-015000
10222025-10-028000
10312025-10-0312000

顧客名と注文金額を同時に表示したい場合、
customer_idをキーにして結合します。

SELECT
    customers.name,
    orders.order_date,
    orders.amount
FROM
    customers
INNER JOIN orders
    ON customers.customer_id = orders.customer_id;

このSQLでは、
customersordersを「内部結合(INNER JOIN)」しており、
結果は以下のようになります。

nameorder_dateamount
田中太郎2025-10-015000
鈴木花子2025-10-028000
田中太郎2025-10-0312000

結合の主な種類は以下の3つです。

  • INNER JOIN:両方のテーブルに存在するデータのみを取得
  • LEFT JOIN:左側テーブルのすべてのデータを取得し、右側が一致しない場合はNULL
  • RIGHT JOIN:右側テーブルのすべてのデータを取得(LEFTの逆)

副問い合わせ(サブクエリ)とは?基本の考え方

副問い合わせとは、SQL文の中で別のSQL文を入れ子にして使う構文のことです。

たとえば、注文テーブルから「平均金額より高い注文」を抽出したい場合、
次のように書けます。

SELECT *
FROM orders
WHERE amount > (
    SELECT AVG(amount)
    FROM orders
);

ここで括弧内の SELECT AVG(amount) が副問い合わせです。
副問い合わせは一時的に別の計算結果を得るために使われ、メインのSELECT文の条件として利用できます。

副問い合わせの種類は大きく3つに分かれます。

  1. スカラ副問い合わせ:1つの値を返す(上の例がこれ)
  2. 行副問い合わせ:1行のデータを返す
  3. テーブル副問い合わせ:複数行を返す(FROM句で使用)

結合と副問い合わせの違い

項目結合(JOIN)副問い合わせ(サブクエリ)
処理対象複数テーブルを結びつける一時的な結果を他のクエリで利用する
可読性複雑になると見づらい単純な条件なら見やすい
実行速度高速(インデックスを使える)条件によっては遅くなる
主な用途テーブルの結合表示条件付きの絞り込み、計算結果の利用

結論としては、
「関連データを横に並べたいときは結合」
「条件や集計結果を条件として使いたいときは副問い合わせ」です。


結合と副問い合わせを同時に使う状況とは?

実際の業務では、結合と副問い合わせを「組み合わせて」使う場面も多くあります。

代表的なケースは次のようなものです。

  1. 結合したデータに対して、さらに別の条件を副問い合わせで絞り込みたいとき
  2. 特定の集計値(例:平均、最大値)を条件に結合結果を制御したいとき
  3. 他のテーブルの存在確認を副問い合わせで行いたいとき

例文①:平均金額より高い注文を顧客名付きで表示

まず、すべての注文の平均金額を副問い合わせで求め、
その結果をもとに、JOINで顧客名を結合します。

SELECT
    c.name,
    o.order_date,
    o.amount
FROM
    customers c
INNER JOIN orders o
    ON c.customer_id = o.customer_id
WHERE
    o.amount > (
        SELECT AVG(amount)
        FROM orders
    );

このSQLの流れを言葉で説明すると、

  1. 副問い合わせ (SELECT AVG(amount) FROM orders) で全体の平均金額を計算
  2. その結果を使って、メインクエリで平均より高い注文を抽出
  3. 抽出結果を customers テーブルと結合して顧客名を取得

結果は、平均金額を上回る顧客と注文が一覧で表示されます。


例文②:特定の都市に住む顧客の注文履歴を取得

次に、顧客テーブルから「東京に住む顧客」のIDだけを副問い合わせで抽出し、
そのIDを条件に orders テーブルと結合して注文履歴を表示します。

SELECT
    o.order_id,
    c.name,
    o.order_date,
    o.amount
FROM
    orders o
INNER JOIN customers c
    ON o.customer_id = c.customer_id
WHERE
    c.customer_id IN (
        SELECT customer_id
        FROM customers
        WHERE city = '東京'
    );

このように、
「副問い合わせで特定条件に合う顧客IDを取得 → 結合で詳細を表示」
という流れを組むことで、柔軟なデータ抽出が可能になります。


例文③:最新注文のみを結合して顧客情報を表示

もう少し発展的な例です。
顧客ごとに「最新の注文」を1件だけ表示したいとき、
副問い合わせを利用して「最新日付の注文ID」を抽出し、
その結果をJOINで結びます。

SELECT
    c.name,
    o.order_date,
    o.amount
FROM
    customers c
INNER JOIN orders o
    ON c.customer_id = o.customer_id
WHERE
    o.order_date = (
        SELECT MAX(order_date)
        FROM orders
        WHERE customer_id = c.customer_id
    );

ここでのポイントは、副問い合わせ内で「外側のテーブル(customers)」を参照している点。
このような構文を**相関サブクエリ(correlated subquery)**と呼びます。

相関サブクエリは、1件ずつ比較・抽出するため処理は重くなりがちですが、
「1件だけ取得したい」など限定的な用途では非常に便利です。


実務での使い分けのコツ

  • 結合で済む場合は結合を使う(副問い合わせは処理コストが高い)
  • 副問い合わせは条件式で使うと読みやすい
  • 相関サブクエリを多用すると遅くなるため、ビュー化や一時テーブル化も検討する
  • SELECT句内の副問い合わせで集計を出すのも有効

実際のSQLチューニングでは、
「結合 → GROUP BY → HAVING」の流れと「副問い合わせを組み合わせる」ことで、
柔軟かつ効率的なデータ抽出が可能になります。


まとめ

SQLの結合と副問い合わせは、それぞれ単体でも強力ですが、
組み合わせることでより柔軟なデータ取得が実現します。

  • 結合:テーブルを横方向に結びつける
  • 副問い合わせ:条件や集計を補助的に利用する
  • 両方を組み合わせる:条件付き結合や最新データ抽出など、実務的な処理が可能

実際の業務では「結合+副問い合わせ」を使う場面は多く、
販売管理、会員データ分析、在庫管理などで頻繁に登場します。

ぜひこの記事の例文を実際に実行して、
「SQLがデータを自在に操るツール」であることを実感してみてください。

タイトルとURLをコピーしました