副問合せとは
あるSQL文の中に SELECT 文を括弧 () で囲んで埋め込む機能。内側の副問合せが先に実行され、その結果が外側の主問合せで利用される。1つの主問合せに埋め込める副問合せの数に制限はなく、副問合せの中にさらに副問合せをネストすることも可能。
副問合せが使用できる句(試験頻出)
| 句 | 副問合せ使用 | 備考 |
|---|---|---|
SELECT |
✅ | スカラー副問合せのみ(1行1列限定) |
FROM |
✅ | インライン・ビューとも呼ばれる |
WHERE |
✅ | 最も多用される |
HAVING |
✅ | 集計後の条件に副問合せを使える |
ORDER BY |
✅ | 並べ替えの基準として副問合せを使える |
| INSERT / UPDATE / DELETE 文 | ✅ | DML文でも使用可能 |
補足:
GROUP BY句には副問合せを直接使用できない。
スカラー副問合せ(単一行・単一列を返す副問合せ)
「1行かつ1列」の値(=スカラー値)を返す副問合せ。「ある1つの値」を指定できる場所であればほぼどこでも使用可能。
-- WHERE句でのスカラー副問合せ(平均給与より高い社員を取得)
SELECT empno, ename, sal
FROM emp
WHERE sal > (SELECT AVG(sal) FROM emp);
-- SELECT句でのスカラー副問合せ(各行に全体平均を表示)
SELECT ename, sal, (SELECT AVG(sal) FROM emp) AS avg_sal
FROM emp;
-- HAVING句でのスカラー副問合せ
SELECT deptno, AVG(sal)
FROM emp
GROUP BY deptno
HAVING AVG(sal) > (SELECT AVG(sal) FROM emp);
スカラー副問合せのエラーになるケース
| ケース | 結果 |
|---|---|
| 複数行を返す | エラー(ORA-01427: 単一行副問合せにより複数の行が返されます) |
| 複数列を返す | エラー(スカラー副問合せは1列のみ) |
| 0行(条件を満たす行なし) |
NULL を返す |
副問合せが NULL を返す場合(重要)
副問合せが0行を返す(条件を満たす行がない)場合、副問合せの結果は NULL となる。
NULL に対して「NULL条件(IS NULL / IS NOT NULL)以外」の条件を指定すると、**条件の評価結果が UNKNOWN(不明)**となるため、SELECT 文は行を返さない。
-- 副問合せが NULL を返した場合
WHERE sal = NULL -- ❌ 条件はUNKNOWN → 行が返らない
WHERE sal IS NULL -- ✅ NULL条件なので正しく評価される
FROM句の副問合せ(インライン・ビュー)
FROM 句に副問合せを記述すると、その結果が**仮想テーブル(インライン・ビュー)**として扱われ、主問合せはそのテーブルに対してクエリを実行する。
-- インライン・ビューの例(部門10の社員から、さらに給与1000以上を抽出)
SELECT empno, ename, sal
FROM (SELECT empno, ename, sal
FROM emp
WHERE deptno = 10) dept10_emp
WHERE sal >= 1000;
表別名について:Oracle Database では
FROM句の副問合せ(インライン・ビュー)に表別名を付けることは技術的には必須ではないが、可読性向上・コーディング規約の観点から常に表別名を付けることが推奨される。
なお MySQL ではエラーになるため必須(Oracle との挙動の違いに注意)。
非スカラー副問合せ
「1行1列」以外を返す副問合せの総称。戻り値の形式によって3種類に分類される。
① 複数行・1列を返す副問合せ
WHERE 句で使用し、IN / ANY / ALL などの複数の値を扱える演算子と組み合わせる。
IN条件
返された値のいずれかに等しい行を真(TRUE)とする。
-- 部門20または30に所属する社員を取得(INで複数値と照合)
SELECT ename
FROM emp
WHERE deptno IN (SELECT deptno FROM dept WHERE loc IN ('DALLAS', 'CHICAGO'));
=ANY(...) は IN(...) と等価。
ANY条件(SOME演算子と同義)
返された値のうちいずれか1つが直前の比較演算子を満たす場合に真。
使用できる比較演算子:= != > >= < <= <>
| 式 | 意味 | 論理展開 |
|---|---|---|
列 < ANY(X,Y,Z) |
X・Y・Zのいずれかより小さい | (列<X) OR (列<Y) OR (列<Z) |
列 > ANY(X,Y,Z) |
X・Y・Zのいずれかより大きい | (列>X) OR (列>Y) OR (列>Z) |
列 = ANY(X,Y,Z) |
X・Y・Zのいずれかと等しい = IN と同義 | (列=X) OR (列=Y) OR (列=Z) |
SELECT ename, sal
FROM emp
WHERE sal > ANY (SELECT sal FROM emp WHERE deptno = 30);
-- 部門30の誰かより給与が高い社員を返す(最小値より大きければ真)
ALL条件
返された値のすべてが直前の比較演算子を満たす場合に真。
使用できる比較演算子:= != > >= < <= <>
| 式 | 意味 | 論理展開 |
|---|---|---|
列 < ALL(X,Y,Z) |
X・Y・Zすべてより小さい | (列<X) AND (列<Y) AND (列<Z) |
列 > ALL(X,Y,Z) |
X・Y・Zすべてより大きい | (列>X) AND (列>Y) AND (列>Z) |
列 = ALL(X,Y,Z) |
X・Y・Zすべてと等しい | (列=X) AND (列=Y) AND (列=Z) |
SELECT ename, sal
FROM emp
WHERE sal > ALL (SELECT sal FROM emp WHERE deptno = 30);
-- 部門30の全員より給与が高い社員を返す(最大値より大きければ真)
NOT INと<> ALLの等価性:列 NOT IN (X,Y,Z)は列 <> ALL(X,Y,Z)と等価。ANY/ALL と NULL の注意点:副問合せが返すリストに
NULLが含まれる場合:
ALLの場合、NULLとの比較が UNKNOWN になるため条件全体が UNKNOWNとなり、行が返らないことがあるNOT INに NULL が含まれると、同様に行が返らないため特に注意が必要
② 1行・複数列を返す副問合せ(行副問合せ)
WHERE 句の右辺や UPDATE 文の SET 句で「1行複数列」を返す副問合せを指定できる。
-- WHERE句で行副問合せ(empno=7521と同じ部門・職種の社員を取得)
SELECT ename, deptno, job
FROM emp
WHERE (deptno, job) = (SELECT deptno, job FROM emp WHERE empno = 7521);
-- UPDATE SET句で行副問合せ(複数列を一括更新)
UPDATE emp
SET (sal, comm) = (SELECT sal, comm FROM emp WHERE empno = 7499)
WHERE empno = 7521;
-
SELECTリストの列数と、左辺の列数が一致している必要がある - 副問合せが2行以上を返す場合はエラー
③ 複数行・複数列を返す副問合せ
主に FROM 句(インライン・ビュー)として使用し、仮想テーブルとして主問合せで扱う。WHERE 句で直接使う場合は IN と行リストの形式で指定する(Oracle のバージョンや構文により異なる)。
-- FROM句(インライン・ビュー)として使用
SELECT e.ename, avg_sal.avg
FROM emp e,
(SELECT deptno, AVG(sal) AS avg
FROM emp
GROUP BY deptno) avg_sal
WHERE e.deptno = avg_sal.deptno;
副問合せの種類・比較まとめ
| 分類 | 返す値の形 | 主な使用箇所 | 使用可能な演算子 |
|---|---|---|---|
| スカラー副問合せ | 1行・1列 | SELECT / WHERE / HAVING / ORDER BY |
= != > >= < <= 単一比較演算子 |
| 複数行副問合せ | 複数行・1列 | WHERE | IN / ANY / ALL / NOT IN |
| 行副問合せ | 1行・複数列 | WHERE / UPDATE SET |
= !=(行リスト) |
| インライン・ビュー | 複数行・複数列 | FROM | — |
試験で意識したいポイントまとめ
| ポイント | 内容 |
|---|---|
| 副問合せが使える句 | SELECT / FROM / WHERE / HAVING / ORDER BY(GROUP BYは不可) |
| スカラー副問合せのエラー | 複数行 or 複数列を返すとエラー |
| 副問合せがNULLを返す場合 | NULL条件以外の条件はUNKNOWNになり行を返さない |
| FROM句の副問合せ | インライン・ビューとも呼ぶ。表別名の付与を推奨 |
=ANY と IN は同義 |
列=ANY(X,Y,Z) = 列 IN(X,Y,Z)
|
<>ALL と NOT IN は同義 |
列<>ALL(X,Y,Z) = 列 NOT IN(X,Y,Z)
|
=ALL(X,Y,Z) の論理展開 |
(列=X) AND (列=Y) AND (列=Z)(元の記事は誤記) |
| NOT INとNULL | 副問合せ結果にNULLが含まれると行が返らない |
| UPDATE SET句の行副問合せ | 左辺の列数と副問合せの列数を一致させる必要がある |