サブクエリ・CTE さぶくえり・しーてぃーいー
サブクエリCTEWITH句共通テーブル式再帰クエリSQL
サブクエリ・CTEについて教えて
簡単に言うとこんな感じ!
サブクエリは「SQLの中にSQLを入れ子にする」仕組み、CTEは「名前付きの一時的な問い合わせ結果を使い回す」仕組みだよ!「平均より高い商品を探す」とか「月次集計を使って前月比を出す」みたいな複雑な問い合わせを、読みやすく段階的に書けるのが強みなんだ!
サブクエリ・CTEとは
サブクエリ(Subquery)とは、SQLの中に別のSELECT文を埋め込む構文です。外側のクエリ(メインクエリ)が結果を参照する「内側のクエリ」です。WHERE句・FROM句・SELECT句など様々な場所に記述できます。「全商品の平均価格より高い商品を取得する」のように、「まず内側を実行してその結果を外側で使う」2段階の処理を1つのSQLで表現できます。
CTE(Common Table Expression:共通テーブル式)は、WITH句を使ってサブクエリに名前を付け、後続のクエリで繰り返し参照できるようにした構文です。SQL:1999で標準化されました。CTEはサブクエリと比べて可読性が高く、デバッグが容易で、同じ結果セットを複数回参照できる利点があります。
CTEの特別な応用として再帰CTE(Recursive CTE)があります。WITH RECURSIVEを使うことで、組織の上下関係・カテゴリの階層・ツリー構造などの再帰的なデータを1つのSQLで辿ることができます。これはサブクエリでは実現が難しい複雑な処理です。
サブクエリの種類
| 種類 | 場所 | 特徴 | 例 |
|---|---|---|---|
| スカラーサブクエリ | SELECT句・WHERE句 | 1行1列の値を返す | AVG価格をSELECTで使う |
| インラインビュー | FROM句 | テーブルのように扱える | 集計済み結果を FROM で使う |
| 相関サブクエリ | WHERE句 | 外側のクエリの値を参照 | 各部門の最高給与を求める |
| EXISTS/IN サブクエリ | WHERE句 | 存在チェック・リスト絞り込み | 注文のある顧客だけを取得 |
歴史と背景
- 1974年:IBM SEQUELでサブクエリの概念が実装
- 1987年:SQL-87でサブクエリが標準化
- 1999年:SQL:1999でCTE(WITH句)と再帰CTEが標準化
- 2000年代:PostgreSQL・Oracle・SQL Serverが相次いでCTE対応
- 2018年:MySQL 8.0でCTEに対応(長らく未対応だった)
- 現在:CTEはSQL可読性向上のベストプラクティスとして広く推奨される
サブクエリ vs CTE の使い分け
| 観点 | サブクエリ | CTE |
|---|---|---|
| 可読性 | ネストが深いと読みにくい | 名前付きで構造が明確 |
| 再利用 | 同じ結果を複数回使えない | 複数回参照可能 |
| デバッグ | WITH部分だけ実行できない | WITH部分だけ実行可能 |
| 再帰 | 不可 | 可能(RECURSIVE) |
| パフォーマンス | DBにより最適化が異なる | 多くのDBでサブクエリと同等 |
関連する規格・RFC
| 規格・RFC番号 | 内容 |
|---|---|
| ISO/IEC 9075:1999 | CTE(WITH句)と再帰CTEの標準化 |
| ISO/IEC 9075:2003 | CTEの挙動の詳細規定 |
関連用語
- SQLの基本 — サブクエリ・CTEを使うSELECT文の基礎
- JOIN — サブクエリの代替になるケースがある結合構文
- ウィンドウ関数 — CTEと組み合わせてよく使う高度なSQL機能
- ビュー — CTEの永続版。よく使うクエリをビューとして保存
- マテリアライズドビュー — CTEの結果を事前計算して保存する仕組み
- ストアドプロシージャ — 複雑なサブクエリ・CTEをまとめてDB側に保存する機能