【しーてぃーいー】

CTE(共通テーブル式) とは?

💡 WITH句で「名前を付けた一時テーブル」をSQL内に定義する仕組み
📌 このページのポイント
CTE(WITH句)による一時的な名前付き結果セット WITH 高額注文 AS ( SELECT user_id, SUM(amount) as total FROM orders GROUP BY user_id HAVING total > 10000) 一時テーブル作成 「高額注文」テーブル user_id | total クエリ内でのみ有効 SELECT u.name, h.total FROM users u JOIN 高額注文 h ON u.id = h.user_id 参照 CTEのメリット ・可読性が高い ・サブクエリを名前で再利用 ・再帰CTEで階層データ処理 ・複雑なクエリを分割・整理
CTE(共通テーブル式)のイメージ
ひよこ ひよこ

CTEって何がうれしいの?

ペンギン先生 ペンギン先生

複雑なSQLを段階的に書けること。例えばサブクエリが3重にネストしたSQLは読みにくいけど、CTEで「WITH step1 AS (...), step2 AS (... step1を参照 ...) SELECT ... FROM step2」と書けば、各ステップに名前がついて処理の流れが明確になる。

ひよこ ひよこ

サブクエリとの違いは?

ペンギン先生 ペンギン先生

機能的にはほぼ同じだけど、CTEは名前を付けて定義するから可読性が高い。あと、同じ結果セットを複数回参照する場合、サブクエリだと同じSQLを何度も書くけど、CTEなら1回定義すれば何度でも名前で参照できる。

ひよこ ひよこ

再帰CTEってどういうもの?

ペンギン先生 ペンギン先生

自分自身を参照するCTE。「WITH RECURSIVE」で定義する。組織のツリー構造(社長→部長→課長→...)や、カテゴリの親子階層をたどるのに使う。「初期行(ルート)を取得→その子を取得→さらにその子を取得→...」と再帰的に探索してくれるよ。

ひよこ ひよこ

CTEってビューとは違うの?

ペンギン先生 ペンギン先生

ビューデータベースに保存されて他のクエリからも使える永続的な定義。CTEはそのSQL文の中だけで有効な一時的な定義。使い捨てのビューみたいなものだね。あと注意したいのはCTEのパフォーマンス。PostgreSQLは12以前だとCTEを「最適化の壁」として扱い、CTE内のクエリと外側のクエリを別々に最適化していた。つまり外側のWHERE条件がCTE内に押し込まれない。PostgreSQL 12以降は改善されたけど、MySQLは8.0でCTEに対応したものの最適化の挙動はバージョンで異なる。「読みやすいけどサブクエリより遅い」ケースがあることは頭に入れておいたほうがいいよ。

ペンギン
まとめ:ざっくりこれだけ覚えればOK!
CTEって出てきたら「WITH句で一時的な名前付き結果セットを作って、SQLを読みやすくする仕組み」と思えばだいたいOK!
📖 おまけ:英語の意味
「Common Table Expression」 = 共通の(Common)テーブル(Table)式(Expression)
💬 SQL内で共通して使える一時的なテーブル表現という意味
← 用語集にもどる