CTE最直接好处是提升复杂查询的可读性与可维护性,通过WITH定义命名中间结果实现逻辑分层,支持多CTE互引和递归处理层级数据,但不提升性能且需避免滥用。

用 CTE(Common Table Expressions,公用表表达式)写 SQL,最直接的好处是让复杂查询更易读、更易维护——它把嵌套的子查询“提出来”,命名后像临时视图一样使用,逻辑分层清晰,改一处不影响全局。
用 WITH 定义可复用的中间结果
CTE 的核心是 WITH 子句,把一段查询结果起个名字,后续 SELECT 就能直接引用。尤其适合需要多次使用的计算结果,比如用户订单总数、某类商品的平均价格等。
- 语法简单:以 WITH name AS (subquery) 开头,后面跟主查询
- 支持多个 CTE:用逗号分隔,彼此可引用(前一个可被后一个用,但不能循环依赖)
- 作用域仅限当前语句:执行完就消失,不占数据库资源,比建临时表轻量得多
拆解多层嵌套,让逻辑一目了然
传统写法中,WHERE 里套子查询、SELECT 里再套子查询,容易看晕。CTE 把每一步“提炼成步骤名”,比如:
- active_users:筛选近30天登录过的用户
- user_orders:关联订单,统计每人下单次数
- top_customers:取下单超过5次的用户
- 最后主查询只写 SELECT * FROM top_customers
这样别人一眼看懂你“先筛人、再算单、最后挑高价值客户”,而不是在一堆括号里找哪段对应哪步。
递归 CTE 处理树形或层级数据
当需要查部门上下级、评论回复链、BOM 物料清单这类有父子关系的数据时,普通 JOIN 很难写清楚。递归 CTE 用 UNION ALL 连接锚点查询和递归部分,天然适配层级遍历。
- 必须包含两个部分:初始查询(锚点) + 递归查询(JOIN 到自身)
- 需加终止条件,比如 WHERE level 防止无限循环
- 常配合 LEVEL 或 PATH 字段,直观展示层级深度或路径
注意事项:别为了用而用
CTE 不是银弹。它不提升性能(多数情况下会被优化器展开为子查询),也不保存数据。滥用反而增加理解成本:
- 单次使用的简单子查询,没必要硬套 CTE
- 过度拆分(比如每个字段都单独一个 CTE)会让代码冗长
- 嵌套太深或命名模糊(如 cte1、cte2)会削弱可读性
真正的好 CTE,名字准确、职责单一、步骤合理——让人不看注释也能猜出它在干什么。










