【SQL & データベース入門】サブクエリとネストされたクエリの活用法|複雑なクエリを簡単に

サブクエリとネストされたクエリとは何か?

サブクエリの概要

サブクエリとは、SQL文の中に埋め込まれた別のSQL文のことです。通常、SELECT文、INSERT文、UPDATE文、DELETE文の中で使用され、データを動的に取得したり、条件として使用することができます。

サブクエリのメリット

  • 動的な条件設定が可能:他のクエリの結果に基づいて条件を決定できます。
  • 可読性の向上:複雑な条件を分解することで、クエリの構造が理解しやすくなります。
  • 柔軟なクエリの設計:複数の条件を組み合わせた高度な検索が可能です。

ネストされたクエリとの違い

サブクエリとネストされたクエリはしばしば同じ意味で使われますが、厳密にはサブクエリは「ネストされたクエリ」の一部です。ネストされたクエリは、1つのSQL文内で複数のクエリが入れ子構造になったもの全般を指します。

サブクエリの基本構文

サブクエリの構文

SELECT 列名 FROM テーブル名 WHERE 条件列 IN (
    SELECT 列名 FROM 他のテーブル WHERE 条件
);
  • 外側のクエリ(メインクエリ)がサブクエリの結果を使用してデータを取得します。
  • サブクエリは括弧で囲む必要があります。

サブクエリの種類

  • スカラーサブクエリ:1つの値を返すサブクエリ
  • 複数行サブクエリ:複数の行を返すサブクエリ
  • 相関サブクエリ:外側のクエリに依存して動的に結果が変わるサブクエリ

サブクエリの使用例

1. WHERE句でのサブクエリ

特定の条件に一致するデータを取得するために、サブクエリをWHERE句で使用する例です。

: 注文が存在するすべての顧客情報を取得する。

SELECT * FROM customers
WHERE customer_id IN (
    SELECT customer_id FROM orders
);
  • 内側のサブクエリで注文した顧客IDを取得し、それを外側のクエリで使用します。

2. SELECT句でのサブクエリ

サブクエリをSELECT句に使用して、計算結果を動的に取得することができます。

: 各顧客の最新の注文日を取得する。

SELECT name, (
    SELECT MAX(order_date) FROM orders WHERE customers.customer_id = orders.customer_id
) AS latest_order_date
FROM customers;
  • 内側のサブクエリが各顧客の最新の注文日を計算し、外側のクエリで表示します。

3. FROM句でのサブクエリ

サブクエリをFROM句に使用すると、サブクエリの結果をテーブルのように扱えます。

: 各商品の注文数を計算して、その結果を基に再度クエリを実行する。

SELECT product_name, total_orders
FROM (
    SELECT product_id, COUNT(*) AS total_orders
    FROM orders
    GROUP BY product_id
) AS order_summary
JOIN products ON order_summary.product_id = products.product_id;
  • サブクエリで各商品の注文数を集計し、その結果を外側のクエリで商品情報と結合しています。

相関サブクエリ

相関サブクエリの概要

相関サブクエリは、外側のクエリの各行に対して動的にサブクエリが実行されるものです。通常のサブクエリと異なり、サブクエリの実行ごとに外側のクエリの値が変化します。

基本構文

SELECT 列名 FROM テーブル名 AS 外側
WHERE 条件列 = (
    SELECT 列名 FROM 他のテーブル AS 内側
    WHERE 外側.列名 = 内側.列名
);

実際の使用例

各社員の給与が、その社員が所属する部署内で最高額かどうかを判定します。

SELECT employee_id, name, salary
FROM employees AS e
WHERE salary = (
    SELECT MAX(salary)
    FROM employees AS sub_e
    WHERE e.department_id = sub_e.department_id
);
  • 内側のクエリが各部署の最大給与を計算し、外側のクエリがその値に一致する社員を取得します。

サブクエリのパフォーマンス最適化

インデックスの適用

サブクエリで使用するテーブルに適切なインデックスを設定することで、検索速度が向上します。特に、サブクエリで使用される結合列や条件列にインデックスを設定することが重要です。

サブクエリの代わりにJOINを使用

場合によっては、サブクエリを使用するよりもJOINを使ったほうがパフォーマンスが良いことがあります。

: サブクエリをJOINに変換する。

-- サブクエリバージョン
SELECT name FROM customers
WHERE customer_id IN (
    SELECT customer_id FROM orders
);

-- JOINバージョン
SELECT DISTINCT customers.name
FROM customers
JOIN orders ON customers.customer_id = orders.customer_id;

JOINを使用することで、より効率的にデータを結合できる場合があります。

サブクエリの注意点

実行回数の増加

相関サブクエリは外側のクエリの各行ごとに実行されるため、大量のデータがある場合はパフォーマンスに悪影響を与える可能性があります。そのため、必要に応じてインデックスを活用したり、JOINに置き換えることを検討しましょう。

スカラーサブクエリの使用に注意

スカラーサブクエリが複数の行を返す場合、エラーになることがあります。そのため、結果が1つの値になることを保証するように設計することが重要です。

まとめ

サブクエリとネストされたクエリは、複雑な条件を含むクエリをシンプルに記述するための強力なツールです。WHERE句、SELECT句、FROM句などさまざまな場面で活用でき、動的な条件設定やデータ集計に役立ちます。ただし、相関サブクエリはパフォーマンスに影響を与える可能性があるため、適切な最適化やJOINの活用を考慮することが重要です。