SQLは「クエリ」とも呼ばれます。 サブクエリ(副問い合わせ)とは、 SQL文の内部に含まれる別のSQL文のことを指します。サブクエリを活用することで、通常のSQLでは取得しにくい複雑な条件のデータを効率的に取得できます。
実際の開発現場では、 複数のサブクエリが組み合わさった複雑なSQLを保守(修正や管理)する必要がある場面が度々あります。 新人プログラマにとっては困難な作業です。
しかし、サブクエリの基本を理解すれば、複雑なSQLに対処できるようになります。今回のレッスンでは、サブクエリの読み解き方を学べます。まずは"その1"、WHERE句にサブクエリを指定するケースです。
SELECT カラム名 FROM テーブル名
WHERE カラム名 = (SELECT カラム名 FROM 別のテーブル WHERE 条件);
最も高い給与を持つ従業員を情報を取得する、よくある要件ですが、実はこれはサブクエリを使わねば取得できないケースです。
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 |
実務ではいくつかのサブクエリが紐づいた複雑な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も単体で見ると分かりやすいですね。
結果例:各部署ごとの最大給与リスト
max_salary |
---|
700000 |
700000 |
550000 |
2.中間のサブクエリ:
SELECT id FROM employees WHERE salary IN(
...各部署ごとの最大給与リスト));
salary
が上記で取得した各部署ごとの最大給与リストと一致する従業員の
id
リストを取得します。
結果例: 従業員のidリスト
id |
---|
3 |
5 |
4 |
3.最も外側のクエリ:
SELECT * FROM employees WHERE id IN (...従業員のidリスト)
最終的な結果:
id | name | salary | department_id |
---|---|---|---|
3 | 佐藤 | 700000 | 1 |
5 | 山本 | 700000 | 2 |
4 | 高橋 | 550000 | 3 |
サブクエリが多数含まれる複雑なSQLは最も内側のサブクエリから順番に読み解きましょう。
💡
補足
サブクエリを使用せず、PHPなどのプログラミング言語側でロジックを組むことで対応することも可能です。サブクエリを使用するか、プログラムで処理するかの判断はプログラマに委ねられています。
もしサブクエリが苦手な場合は、プログラミング言語でカバーする方法を検討するのも一つの選択肢です。
以下の売上テーブル(sales)を使用して、サブクエリを活用したSQLを学習しましょう。
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 |
最も高い売上額を持つ取引(id, customer name, salesamount, sales_date)を取得するSQLを記述してください。
2月の売上の平均額よりも高い売上を記録した取引を取得するSQLを記述してください。
2024年2月1日以前に発生した取引の中で、最も高い売上額を持つ取引を取得するSQLを記述してください。
最も古い取引を行った顧客の情報を取得するSQLを記述してください。
解答例を考えながらSQLを実践してみましょう!