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' pipeline 聚合实现同样的效果。

在 DBAtlas 中打开 →