サブクエリ(スカラー・行)
| 対応: | SQL-92(1992) |
|---|
クエリの中に別のSELECT文を埋め込んだものをサブクエリと呼びます。スカラーサブクエリは必ず1列1行の単一値を返し、行サブクエリは1行複数列を返します。
構文
スカラーサブクエリ: SELECT列・WHERE条件・SET句などに単一値として埋め込みます。
SELECT column_name, (SELECT aggregate_function(...) FROM ...) AS alias FROM table_name;
WHERE句でスカラーサブクエリを使います。
SELECT column_name FROM table_name WHERE column_name = (SELECT single_value FROM ...);
行サブクエリ: 複数列を比較します。
SELECT column_name FROM table_name WHERE (col_a, col_b) = (SELECT col_a, col_b FROM ... LIMIT 1);
構文一覧
| 種類 | 概要 |
|---|---|
| スカラーサブクエリ | 1列1行の単一値を返すサブクエリです。SELECT列・WHERE・SET句などに使えます。 |
| 行サブクエリ | 1行複数列を返すサブクエリです。行値式と組み合わせて複数列を一度に比較できます。 |
サンプルコード
以下の『employees』テーブルを例に説明します。
各社員の給与と全社員の平均給与を並べて表示します(スカラーサブクエリ)。
sample_subquery_scalar.sql
SELECT
name,
salary,
(SELECT AVG(salary) FROM employees) AS avg_salary,
salary - (SELECT AVG(salary) FROM employees) AS diff_from_avg
FROM employees
ORDER BY salary DESC;
+------------+--------+------------+---------------+ | name | salary | avg_salary | diff_from_avg | +------------+--------+------------+---------------+ | 常守朱 | 620000 | 452500 | 167500 | | 狡噛慎也 | 480000 | 452500 | 27500 | | 宜野座伸元 | 390000 | 452500 | -62500 | | 征陸智己 | 320000 | 452500 | -132500 | +------------+--------+------------+---------------+ 4 rows in set
最も給与が高い社員を取得します。
sample_subquery_scalar.sql
SELECT name, salary FROM employees WHERE salary = (SELECT MAX(salary) FROM employees);
+--------+--------+ | name | salary | +--------+--------+ | 常守朱 | 620000 | +--------+--------+ 1 row in set
以下は発展的な使い方です。最も給与が高い社員と同じ給与・部署の社員を行サブクエリで検索します。
sample_subquery_scalar.sql
SELECT name, salary, department
FROM employees
WHERE (salary, department) = (
SELECT salary, department
FROM employees
ORDER BY salary DESC
LIMIT 1
);
+--------+--------+------------+ | name | salary | department | +--------+--------+------------+ | 常守朱 | 620000 | 監視官 | +--------+--------+------------+ 1 row in set
データベース別の書き方
スカラーサブクエリの構文は主要なデータベースで共通して使用できます。
SELECT name, salary, (SELECT AVG(salary) FROM employees) AS avg_salary FROM employees ORDER BY salary DESC;
行サブクエリで結果を1行に制限する書き方はデータベースごとに異なります。MySQL・PostgreSQL・SQLite は『LIMIT 1』を使用します。
SELECT name, salary, department
FROM employees
WHERE (salary, department) = (
SELECT salary, department FROM employees ORDER BY salary DESC LIMIT 1
);
Oracle は『FETCH FIRST 1 ROW ONLY』を使用します(12c 以降)。それ以前のバージョンでは『ROWNUM』で制限します。
SELECT name, salary, department
FROM employees
WHERE (salary, department) = (
SELECT salary, department FROM employees ORDER BY salary DESC
FETCH FIRST 1 ROW ONLY
);
概要
『スカラーサブクエリ』は結果が必ず1列1行でなければなりません。2行以上を返すと実行時エラーになります。集計関数(MAX・MIN・AVG・COUNT)を使うと自然に1行になるため、スカラーサブクエリと相性が良いです。
スカラーサブクエリはSELECT句・WHERE句・HAVING句・SET句(UPDATE文)など多くの場所で使えます。SELECT句に書くと全行に対して毎回評価されるため、大量データに対しては JOIN や派生テーブルへの書き換えを検討してください。
複数行を返すサブクエリとの比較には『IN / EXISTS』や『ALL / ANY』を使います。外側のクエリを参照するサブクエリは『相関サブクエリ』を参照してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。