1. サブクエリとは?

SQLは「クエリ」とも呼ばれます。 サブクエリ(副問い合わせ)とは、 SQL文の内部に含まれる別のSQL文のことを指します。サブクエリを活用することで、通常のSQLでは取得しにくい複雑な条件のデータを効率的に取得できます。

実際の開発現場では、 複数のサブクエリが組み合わさった複雑なSQLを保守(修正や管理)する必要がある場面が度々あります。 新人プログラマにとっては困難な作業です。

しかし、サブクエリの基本を理解すれば、複雑なSQLに対処できるようになります。今回のレッスンでは、サブクエリの読み解き方を学べます。まずは"その1"、WHERE句にサブクエリを指定するケースです。

2. サブクエリの基本構文

SELECT カラム名 FROM テーブル名
WHERE カラム名 = (SELECT カラム名 FROM 別のテーブル WHERE 条件);

3. サブクエリの使用例

3.1 WHERE句での利用

最も高い給与を持つ従業員を情報を取得する、よくある要件ですが、実はこれはサブクエリを使わねば取得できないケースです。

従業員テーブル (employees)

id name salary department_id
1 田中 500000 1
2 鈴木 600000 2
3 佐藤 700000 1
4 高橋 550000 3
5 山本 700000 2

最も高い給与を持つ従業員を検索

SELECT * FROM employees
WHERE salary = (SELECT MAX(salary) FROM employees);
まず、内側のクエリである、サブクエリ「SELECT MAX(salary) FROM employees」で最大給与を取得します。 そして外側のクエリで最大給与に一致する給与の従業員情報を取得します。

結果:

id name salary department_id
3 佐藤 700000 1
5 山本 700000 2

3.2 複数のサブクエリからなる複雑なSQLを読み解く

実務ではいくつかのサブクエリが紐づいた複雑なSQLに直面することが度々あります。次の例のSQLクエリは、3つの入れ子になったサブクエリを持っている、やや複雑なSQLです。初心者は複雑のSQLを見ると圧倒されるものですが、 最も内側のSQLから順番に見ていけば大丈夫です

SELECT * FROM employees
WHERE id IN (
  SELECT id FROM employees WHERE salary IN(
    SELECT MAX(salary) FROM employees GROUP BY department_id));

1.最も内側のサブクエリ:

    SELECT MAX(salary) FROM employees GROUP BY department_id

まずは一番内側のクエリから読み解きます。このサブクエリは、各部署ごとの最大給与リストを取得しているだけです。複雑なSQLも単体で見ると分かりやすいですね。


2.中間のサブクエリ:


  SELECT id FROM employees WHERE salary IN(
    ...各部署ごとの最大給与リスト));

3.最も外側のクエリ:

   SELECT * FROM employees WHERE id IN (...従業員のidリスト)

最終的な結果:

id name salary department_id
3 佐藤 700000 1
5 山本 700000 2
4 高橋 550000 3

4. まとめ

サブクエリが多数含まれる複雑なSQLは最も内側のサブクエリから順番に読み解きましょう。

💡 補足
サブクエリを使用せず、PHPなどのプログラミング言語側でロジックを組むことで対応することも可能です。サブクエリを使用するか、プログラムで処理するかの判断はプログラマに委ねられています。
もしサブクエリが苦手な場合は、プログラミング言語でカバーする方法を検討するのも一つの選択肢です。


練習問題:サブクエリの理解と実践

以下の売上テーブル(sales)を使用して、サブクエリを活用したSQLを学習しましょう。

売上テーブル(sales)

id customer_name sales_amount sales_date
1 田中 15000 2024-01-10
2 鈴木 22000 2024-01-12
3 佐藤 18000 2024-02-05
4 高橋 25000 2024-02-10
5 山本 20000 2024-03-15

問題1:最も高い売上額の取引を取得

最も高い売上額を持つ取引(id, customer name, salesamount, sales_date)を取得するSQLを記述してください。


問題2:特定の売上額を超える取引を取得

2月の売上の平均額よりも高い売上を記録した取引を取得するSQLを記述してください。


問題3:特定の日付以前の最大売上

2024年2月1日以前に発生した取引の中で、最も高い売上額を持つ取引を取得するSQLを記述してください。


問題4:最も古い取引を持つ顧客

最も古い取引を行った顧客の情報を取得するSQLを記述してください。


解答例を考えながらSQLを実践してみましょう!