一个 CTE (Common Table Expression),用 WITH 定义,是一个命名的临时结果集,你可以在查询中引用它。CTEs 通过将复杂查询分解为命名的逻辑步骤来提高 可读性 — 并且它们启用 递归 查询(用于层级数据)。
一个基本的 CTE — 为了可读性给子查询命名
active_users (
id, name users active
)
active_users
name ;
一个 CTE (Common Table Expression),用 WITH 定义,是一个命名的临时结果集,你可以在查询中引用它。CTEs 通过将复杂查询分解为命名的逻辑步骤来提高 可读性 — 并且它们启用 递归 查询(用于层级数据)。
active_users (
id, name users active
)
active_users
name ;
WITH ... AS (...) 定义一个 CTE — 一个命名查询,你稍后引用它。它像一个子查询,但是 命名且可读,特别是对于复杂查询。
WITH
monthly_sales AS (
SELECT month, SUM(amount) AS total FROM orders GROUP BY month
),
avg_sales AS (
SELECT AVG(total) AS avg_total FROM monthly_sales -- a CTE can reference another
)
SELECT m.month, m.total
FROM monthly_sales m, avg_sales a
WHERE m.total > a.avg_total; -- months above the average
多个 CTEs 将复杂查询分解为可读的、按顺序的步骤 — 每一个都建立在前一个之上。这比深层嵌套子查询清晰得多。
Nested subqueries → hard to read when deeply nested
CTEs → name each step, read top-to-bottom like a sequence → much clearer
→ CTEs are often preferred for COMPLEX queries purely for readability/maintainability.
-- traverse a hierarchy (e.g. all descendants of a category, an org chart)
WITH RECURSIVE subordinates AS (
SELECT id, name, manager_id FROM employees WHERE id = 1 -- base case (the top)
UNION ALL
SELECT e.id, e.name, e.manager_id
FROM employees e
JOIN subordinates s ON e.manager_id = s.id -- recursive step
)
SELECT * FROM subordinates; -- the whole tree under employee 1
递归 CTEs (WITH RECURSIVE) 遍历层级/树形数据(组织结构图、分类树、物料清单、图形路径) — 在 SQL 中这通常很困难。
CTEs 是用于 可读性和递归 的重要 SQL 功能,理解它们对于编写可维护的复杂查询以及处理层级数据很有价值。
日常使用的主要好处是 可读性:具有多层子查询的复杂查询变得难以阅读和维护,而 CTEs 让你可以将查询分解为命名的、按顺序的逻辑步骤(从上到下阅读,如同一系列操作),大大提高了清晰度 — 因此,对于复杂查询,CTEs 通常比深层嵌套子查询更受欢迎,使其成为编写可维护 SQL 的重要工具。
同样重要的是 递归 CTE 的能力 (WITH RECURSIVE),它能够查询 层级和树形结构的数据(组织结构、分类树、物料清单、图形遍历) — 这类查询在标准 SQL 中通常很困难或不可能,使递归 CTEs 成为层级数据遍历的标准解决方案。
理解两种用途 — 用于将复杂查询分解为可读步骤的 CTEs,以及用于层级遍历的递归 CTEs — 覆盖了其实际价值。
由于复杂查询在实际应用中很普遍(可读性/可维护性很重要),且层级数据(递归 CTEs 特别擅长处理)经常出现(组织结构、嵌套分类、线性数据),理解 CTEs 是有价值的高级知识,能改进查询可维护性并解锁层级查询 — 这是一个频繁相关的工具,用于编写清洁、复杂的 SQL,也是常见的话题,展示了高级 SQL 能力,特别是用于树形结构数据的递归形式。