DBAtlas · データベース運用アトラス

WITH(共通テーブル式 / CTE)

Oracle

WITH region AS (
  SELECT city, COUNT(*) AS n
  FROM customer
  GROUP BY city
)
SELECT city, n FROM region WHERE n > 10;

WITH はクエリ内に名前付きの一時的な結果セット(CTE)を定義する。サブクエリを繰り返し書く代わりに、一度定義して名前で参照する。複雑なクエリを読みやすい部分に分割できる。Oracle 9i 以降でサポートされる。

PostgreSQL

WITH region AS (
  SELECT city, COUNT(*) AS n
  FROM customer
  GROUP BY city
)
SELECT city, n FROM region WHERE n > 10;

CTE は複雑なクエリを名前付きのブロックに分割する。PostgreSQL 12 より前の CTE は最適化の障壁(常にマテリアライズされる)だった。12 以降はインライン化でき、WITH ... AS MATERIALIZED で旧来の挙動を強制できる。

MySQL

WITH region AS (
  SELECT city, COUNT(*) AS n
  FROM customer
  GROUP BY city
)
SELECT city, n FROM region WHERE n > 10;

CTE はクエリ内で一時的な名前付きの結果セットを定義し、可読性を向上させる。MySQL 8.0(および MariaDB 10.2)以降でサポートされる。古いバージョンでは派生テーブル(FROM 内のサブクエリ)が必要。

SQL Server

WITH region AS (
  SELECT city, COUNT(*) AS n
  FROM customer
  GROUP BY city
)
SELECT city, n FROM region WHERE n > 10;

CTE は名前付きの一時的な結果セット。SQL Server では CTE の直前の文をセミコロンで終える必要があり、そのため WITH はしばしば ';WITH' と書かれる。単一の文(SELECT/INSERT/UPDATE/DELETE)の間だけ有効。

MongoDB

// Closest equivalent: aggregation pipeline stages
db.customer.aggregate([
  { $group: { _id: "$city", n: { $sum: 1 } } },
  { $match: { n: { $gt: 10 } } }
])

MongoDB には SQL/CTE がなく、集計パイプラインのステージが同じ役割を果たす。各ステージは前のステージの出力を入力として受け取り、CTE のチェーンに似た段階的な処理となる。中間結果には $facet や $lookup も使用できる。

Redis

# Not applicable: Redis has no concept of SQL or CTEs.

Redis はクエリ言語を持たないキーバリューのデータストア。中間結果はクライアント側で組み合わせるか、サーバー側のロジックには Lua スクリプト(EVAL)を使用する。

Elasticsearch

# CTEs are not supported in Elasticsearch SQL.
POST _sql
{ "query": "SELECT city, COUNT(*) n FROM customer GROUP BY city HAVING COUNT(*) > 10" }

Elasticsearch SQL(_sql API)は WITH/CTE 構文をサポートしない。グループ化とフィルタリングは単一の SELECT に記述する。ネイティブの方法では、'terms' 集計と 'bucket_selector' パイプライン集計で同じことを行う。

DBAtlas で開く →