ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
| この記事の要点 |
|
副問い合わせとは
SQL の SELECT / WHERE / FROM / HAVING の中に書ける、もう一つの SELECT 文のことを 副問い合わせ (Subquery / 子クエリ) と呼びます。外側のクエリを 主問い合わせ (Outer query) と呼びます。
使いどころは大きく 3 つ。
| 分類 | 返す形 | 典型的な使い場所 |
|---|---|---|
| スカラー副問い合わせ | 1 行 1 列 (1 値) | SELECT のリスト / WHERE 句の比較 |
| 行副問い合わせ | 1 行 N 列 | WHERE (a,b) = (SELECT ...) |
| 列副問い合わせ | N 行 1 列 | WHERE x IN (SELECT ...) / EXISTS |
| インラインビュー | 表 (N 行 N 列) | FROM 句に書く一時表 |
スカラー副問い合わせ
結果が必ず 1 行 1 列に絞れる副問い合わせ。SELECT リストや比較述語の右辺で使えます。
-- 全社員の給与と、会社の平均給与を並べる
SELECT
emp_id,
name,
salary,
(SELECT AVG(salary) FROM employees) AS avg_salary,
salary - (SELECT AVG(salary) FROM employees) AS diff
FROM employees;
-- 自部署より給料が高い人だけ
SELECT name, salary
FROM employees e
WHERE salary > (
SELECT AVG(salary) FROM employees
WHERE dept_id = e.dept_id -- ← 相関副問い合わせ
);
注意: 副問い合わせが 2 行以上返してしまうと ORA-01427 / ERROR 1242 等のエラーが出ます。MAX / MIN / LIMIT 1 等で 1 行に絞ります。
列副問い合わせと IN / NOT IN
-- 「東京」部署の社員一覧
SELECT name FROM employees
WHERE dept_id IN (SELECT dept_id FROM departments WHERE city = '東京');
-- 退職済みでないユーザー
SELECT * FROM users
WHERE user_id NOT IN (SELECT user_id FROM retirements);
NOT IN の罠 — 副問い合わせ側に NULL が 1 件でもあると、x NOT IN (1, 2, NULL) は 「x <> 1 AND x <> 2 AND x <> NULL」 に展開され、最後の比較が UNKNOWN になるため全体が常に偽になります。結果が 0 件 になって悩むのはこれ。
-- NG: retirements.user_id に NULL があると常に 0 件
SELECT * FROM users
WHERE user_id NOT IN (SELECT user_id FROM retirements);
-- OK: NOT EXISTS を使う or NULL を除外
SELECT * FROM users u
WHERE NOT EXISTS (
SELECT 1 FROM retirements r WHERE r.user_id = u.user_id
);
EXISTS / NOT EXISTS
「存在するか」「存在しないか」だけを問う形。副問い合わせ側の値そのものは見ないので、SELECT 1 や SELECT * でも結果は同じです。
-- 注文を 1 件以上持っている顧客
SELECT *
FROM customers c
WHERE EXISTS (
SELECT 1 FROM orders o
WHERE o.customer_id = c.customer_id
);
-- 一度も注文していない顧客
SELECT *
FROM customers c
WHERE NOT EXISTS (
SELECT 1 FROM orders o
WHERE o.customer_id = c.customer_id
);
ANY / SOME / ALL
| 述語 | 意味 | 等価な書き換え |
|---|---|---|
= ANY (...) | いずれか一つと等しい | IN (...) |
<> ALL (...) | すべてと等しくない | NOT IN (...) |
> ANY (...) | 最小値より大きい | > (SELECT MIN(...)) |
> ALL (...) | 最大値より大きい | > (SELECT MAX(...)) |
-- 営業部のどの社員よりも給料が高い人
SELECT name, salary FROM employees
WHERE salary > ALL (
SELECT salary FROM employees WHERE dept_id = 'SALES'
);
-- = SELECT name, salary FROM employees
-- WHERE salary > (SELECT MAX(salary) FROM employees WHERE dept_id = 'SALES');
インラインビュー (FROM 句の副問い合わせ)
-- 部署ごとの平均給与を出して、その中で平均が 50 万以上の部署のみ
SELECT d.dept_name, t.avg_sal
FROM departments d
JOIN (
SELECT dept_id, AVG(salary) AS avg_sal
FROM employees
GROUP BY dept_id
) t ON t.dept_id = d.dept_id
WHERE t.avg_sal >= 500000;
相関副問い合わせ
副問い合わせの中で外側の列を参照する形。外側 1 行ごとに副問い合わせが評価されるため、大量データでは遅くなりがち。可能なら JOIN + GROUP BY に書き換えると速くなります。
-- 部署ごとに最も給料の高い人 (相関版)
SELECT name, dept_id, salary
FROM employees e1
WHERE salary = (
SELECT MAX(salary) FROM employees e2
WHERE e2.dept_id = e1.dept_id -- ← 外側参照
);
-- 同じ結果を JOIN で
SELECT e.name, e.dept_id, e.salary
FROM employees e
JOIN (
SELECT dept_id, MAX(salary) AS max_sal
FROM employees GROUP BY dept_id
) m ON m.dept_id = e.dept_id AND m.max_sal = e.salary;
CTE (WITH) との比較
ネストが深くなると読みづらく、デバッグも面倒です。WITH 句 (Common Table Expression) を使うと、副問い合わせを上から順に名前付きで定義できます。Oracle / PostgreSQL / SQL Server / MySQL 8.0+ で利用可能。
WITH dept_avg AS (
SELECT dept_id, AVG(salary) AS avg_sal
FROM employees
GROUP BY dept_id
),
high_dept AS (
SELECT dept_id FROM dept_avg WHERE avg_sal >= 500000
)
SELECT e.name, e.dept_id, e.salary
FROM employees e
JOIN high_dept h ON h.dept_id = e.dept_id;
性能 — JOIN への置換と Index
| パターン | 性能上の注意 |
|---|---|
列副問い合わせ x IN (SELECT ...) | 多くの DB で内部的に半結合 (semi-join) に最適化される。Index が効くなら速い |
相関 EXISTS | 外側 1 行ごとに 1 件見つかれば打ち切り。一般に IN より高速 |
| NOT IN (NULL 含む) | 結果 0 件のバグ + 性能も劣化 — NOT EXISTS に書換 |
| スカラー副問い合わせを SELECT に書く | 外側 1 行ごとに評価され遅い — JOIN + GROUP BY が高速なケースが多い |
| FROM 句の副問い合わせ | マテリアライズされる DB と、外側にプッシュダウンされる DB がある — EXPLAIN で確認 |
ネストの深さ制限
| DB | ネスト上限 |
|---|---|
| Oracle | FROM 句で 255 階層、WHERE 内は実質無制限だが推奨は数階層まで |
| SQL Server | 32 階層 |
| MySQL | 明示上限なし。ただし 8.0 未満は派生テーブルの最適化が弱い |
| PostgreSQL | 明示上限なし |
FAQ
Q: 副問い合わせと JOIN、どちらが速いですか?
A: 最近のオプティマイザは両者を同じ実行計画に変換することが多く、差は出にくいです。読みやすさ優先で書き、遅かったら EXPLAIN を見て JOIN や CTE に書き換えるのが定石。
Q: NOT IN と NOT EXISTS の使い分けは?
A: 「副問い合わせ側に NULL が混入し得るなら NOT EXISTS」が安全策。NOT IN は NULL が無いと保証できる列だけに使ってください。
Q: 副問い合わせは何階層までネストして大丈夫?
A: 機能上は深くできますが、可読性とオプティマイザの安定性のため 3 階層を超えたら WITH 句に分解 するのがおすすめです。
ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
子ページはありません
人気ページ
- 1 Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法
- 2 tomcat の起動 / 停止ログと catalina.log・catalina.out の違い
- 3 JavaScript base URL 取得方法|window.location.origin と SSR/Node.js 対応
- 4 YouTube Data API v3 エラー一覧|403/400/404 の主要原因と切り分け
- 5 Spring Frameworkのアノテーション一覧
- 6 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 7 3Dグラフィックスとは|モデリング/レンダリング/主要ソフトウェア (Blender / Maya)
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- IPv6とは|128bitアドレス・コロン16進表記/::省略・リンクローカル・SLAAC・デュアルスタック NEW 2026-06-22 12:34:44
- VPNとは|暗号トンネル・サイト間/リモートアクセス・IPsec/SSL-VPN/WireGuardを解説 NEW 2026-06-22 12:19:10
- MAC アドレスフィルタリングの仕組みと限界 | ネットワーク入門 NEW 2026-06-22 12:19:10
- WebRTC とは ブラウザ間 P2P の音声・映像・データ通信 | ネットワーク入門 NEW 2026-06-22 12:17:25
- gRPC とは HTTP/2 + Protocol Buffers の高速 RPC | ネットワーク入門 NEW 2026-06-22 12:17:25
- HTTP/3 (QUIC) とは UDP ベースの低遅延 Web 通信 | ネットワーク入門 NEW 2026-06-22 12:17:25
- HTTP/2 とは 多重化・HPACK・バイナリフレーム | ネットワーク入門 NEW 2026-06-22 12:17:25
- Web通信プロトコル入門 HTTP/2・HTTP/3・WebSocket・gRPC・WebRTC | ネットワーク入門 NEW 2026-06-22 12:17:25
- WebSocket とは 全二重リアルタイム通信 ws/wss | ネットワーク入門 NEW 2026-06-22 12:17:25
- ファイアウォールとは|パケットフィルタ・ステートフル・DMZ・次世代FW(L4/L7)を解説 NEW 2026-06-22 12:17:24
- iptables/nftablesとは|テーブル・チェーン・ルール例・永続化をLinux視点で解説 NEW 2026-06-22 12:17:24
- HAProxy とは frontend/backend と設定例 | ネットワーク入門 NEW 2026-06-22 12:17:24
- 証明書と認証局(CA)とは|X.509・信頼チェーン・DV/OV/EV・失効(CRL/OCSP)を解説 NEW 2026-06-22 12:17:24
- CDN とは エッジキャッシュ・TTL・Cloudflare/CloudFront | ネットワーク入門 NEW 2026-06-22 12:17:24
- TLS/SSLの仕組み|ハンドシェイク・暗号スイート・前方秘匿性・証明書検証をわかりやすく解説 NEW 2026-06-22 12:17:24
コメントを削除してもよろしいでしょうか?