• SQL 也能递归?一文搞懂 Recursive CTE的魔力

SQL 也能递归?一文搞懂 Recursive CTE的魔力

2025-06-10 02:00:10 栏目:宝塔面板 135 阅读

很多人以为递归(Recursive)只属于编程语言,和 SQL 没什么关系。但其实 SQL 中也能实现递归操作,特别是在处理树结构、路径查找时,WITH RECURSIVE 展现出强大威力。本文将带你一步步掌握 SQL 中的递归查询,揭开 Recursive CTE 的神秘面纱!

Recursive CTE(递归公共表表达式)

在 SQL 中,递归公共表表达式(Recursive CTE) 是一种强大的查询手段。通过 WITH RECURSIVE 语法,开发者可以定义一个可以引用自身的查询结构,实现在查询过程中“自我迭代”的效果。

简单来说,SQL 也能“递归”。

不过需要注意的是,递归查询必须设计得当,确保它在某个条件下能够终止。否则,就可能陷入“无限循环”,导致查询无法完成,甚至拖垮数据库性能。

那么,SQL 的递归到底怎么写?能解决哪些实际问题?接下来,我们就从原理、写法,到典型应用场景,一步步带你搞懂 Recursive CTE 的魔力。

来看一个最简单的例子,生成从 1 到 5 的数字序列:

图片

我们来拆解一下这段 SQL 是如何“递归”的:

  • 首先,SELECT 1 AS num 是 递归的起点,称为锚点(Anchor Member),递归从这里开始。
  • 接下来,SELECT num + 1 FROM rec WHERE num < 5 是 递归部分,它会反复执行,直到 num < 5 不再满足为止。
  • UNION ALL 将锚点和递归部分的结果组合起来。

整个查询的执行过程大致如下:

  1. 第一步,输出 1;
  2. 然后执行递归部分,1 + 1 = 2,满足条件,继续;
  3. 依次得到 3、4、5;
  4. 当 num 增加到 6 时,不满足 num < 5,递归终止。

把递归逻辑“套”起来,这次不是 1 到 5,而是 100、200、300……直到 700。核心逻辑没变,只是换了组数字而已。

图片

示例:斐波那契数列(Fibonacci Sequence)

WITH RECURSIVE 不仅可以用于构造数字序列,还可以实现更复杂的递归计算。比如,我们可以利用它来生成前 8 个斐波那契数:

图片

示例:树结构遍历(Tree Traversal)

除了计算数值,WITH RECURSIVE 还可以用于遍历树形结构,这在处理层级数据(如组织架构、分类标签、菜单结构等)时非常常见。

比如,下面是一个“标签(tags)层级结构”的递归遍历案例:

图片

图片

图片

示例:图遍历(Graph Traversal)

借助 WITH RECURSIVE,我们甚至可以在 SQL 中实现任意图结构的遍历(Graph Traversal)。这对于表示如路线网络、依赖关系图、社交图谱等复杂结构非常有用。

不过需要特别注意的是:如果图中存在环(cycle),就必须进行循环检测,否则递归查询可能会陷入死循环,永远无法终止。

一种常见的做法是:在递归过程中记录当前路径,每次延伸路径前,先检查目标节点是否已访问过,从而避免重复走回头路。下面的示例中详细演示这一做法。

图片

图片

需要注意的是,这类图结构中可能包含有向环(directed cycles),比如节点 1、5 和 8 之间就形成了一个闭环。

枚举从某个节点出发的所有路径(Enumerate All Paths from a Node)

下面这个查询展示了如何使用 WITH RECURSIVE 来枚举从节点 1 出发的所有路径:

图片

需要注意的是,这个查询的结果并不限于最短路径。

例如,对于节点 5,结果中既包含直接路径 [1, 5],也包含更长的路径 [1, 3, 5]。

换句话说,它会列出所有可能走通的路径,而不是只保留最短的那一条。如果你希望过滤最短路径或添加路径权重,还需要进一步处理。

图片

枚举两个节点之间的无权最短路径(Enumerate Unweighted Shortest Paths)

WITH RECURSIVE 还可以用来查找两个节点之间的所有无权最短路径。为了保证递归查询在到达目标节点后及时终止,我们可以借助窗口函数,检查当前新增节点中是否已包含目标节点。

下面的查询展示了如何找出从节点 1(起点)到节点 8(终点)之间的所有无权最短路径:

图片

递归不仅属于编程语言,SQL 也能“递归”!借助 WITH RECURSIVE,我们可以优雅地处理数字序列、树结构、图遍历等复杂问题。无论是层级查询,还是路径搜索,Recursive CTE 都是一种强大且灵活的利器。

本文地址:https://www.yitenyun.com/278.html

搜索文章

Tags

数据库 API FastAPI Calcite 电商系统 MySQL Web 应用 异步数据库 数据同步 ACK 双主架构 循环复制 TIME_WAIT 运维 负载均衡 JumpServer SSL 堡垒机 跳板机 HTTPS HexHub Docker 服务器 管理口 服务器性能 JumpServer安装 堡垒机安装 Linux安装JumpServer Deepseek 宝塔面板 Linux宝塔 生命周期 esxi esxi6 root密码不对 无法登录 web无法登录 SQL 查询 序列 核心机制 Windows Windows server net3.5 .NET 安装出错 HTTPS加密 Windows宝塔 Mysql重置密码 开源 PostgreSQL 存储引擎 锁机制 宝塔面板打不开 宝塔面板无法访问 查看硬件 Linux查看硬件 Linux查看CPU Linux查看内存 行业 趋势 Oracle 处理机制 无法访问宝塔面板 Undo Log 机制 监控 连接控制 InnoDB 数据库锁 Spring Redis 异步化 优化 万能公式 机器学习 动态查询 Serverless 无服务器 语言 ES 协同 响应模型 group by 索引 技术 openHalo scp Linux的scp怎么用 scp上传 scp下载 scp命令 分页查询 Postgres OTel Iceberg 缓存方案 缓存架构 缓存穿透 工具 存储 高可用 GreatSQL 连接数 数据 主库 SVM Embedding R edis 线程 日志文件 MIXED 3 Linux 安全 国产数据库 R2DBC SQLite-Web SQLite 数据库管理工具 加密 场景 Netstat Linux 服务器 端口 启动故障 ​Redis 推荐模型 Recursive 自定义序列化 防火墙 黑客 云原生 RocketMQ 长轮询 配置 SQLark 共享锁 OB 单机版 AI 助手 向量数据库 大模型 Hash 字段 PG DBA Rsync Ftp 信息化 智能运维 不宕机 磁盘架构 电商 系统 架构 向量库 Milvus Canal 数据分类 Python 业务 IT运维 修改DNS Centos7如何修改DNS 分库 分表 流量 传统数据库 向量化 线上 库存 预扣 filelock MVCC • 索引 • 数据库 人工智能 推荐系统 redo log 重做日志 语句 同城 双活 MySQL 9.3 聚簇 非聚簇 sftp 服务器 参数 PostGIS mini-redis INCR指令 频繁 Codis Doris SeaTunnel MongoDB MCP 开放协议 缓存 Redisson 锁芯 失效 高效统计 今天这篇文章就跟大家 工具链 INSERT COMPACT 事务 Java 开发 主从复制 代理 数据备份 数据类型 虚拟服务器 虚拟机 内存 prometheus Alert 千万级 大表 窗口 函数 发件箱模式 SSH 容器 数据结构 ZODB 网络架构 网络配置 EasyExcel MySQL8 引擎 性能 Web 分布式架构 分布式锁​ 聚簇索引 非聚簇索引 QPS 高并发 数据脱敏 加密算法 崖山 新版本 B+Tree ID 字段 RDB AOF 分页 核心架构 订阅机制 速度 服务器中毒 Go 数据库迁移 Web 接口 分布式 集中式 数据集成工具 自动重启 OAuth2 Token Redis 8.0 读写 容器化 网络故障 播客 模型 数据页 DBMS 管理系统 StarRocks 数据仓库 排行榜 排序 池化技术 连接池 微软 SQL Server AI功能 Redka SpringAI JOIN Caffeine CP 原子性 MGR 分布式集群 网络 部署 Entity 事务隔离 LRU 业务场景 Testcloud 云端自动化 Valkey Valkey8.0 Pottery 数据字典 兼容性 dbt 数据转换工具 分页方案 排版 ReadView 优化器 事务同步 1 意向锁 记录锁 sqlmock 关系数据库 悲观锁 乐观锁 单线程 UUIDv7 主键 日志 Weaviate 对象 单点故障 仪表盘 Order AIOPS UUID ID InfluxDB 编程 Pump RAG HelixDB Ansible IT 双引擎 Crash 代码 产业链 分布式锁 Zookeeper 恢复数据 字典 订单 LLM List 类型 线程安全 国产 用户 慢SQL优化 表空间 拦截器 动态代理 解锁 调优 Next-Key RR 互联网 GitHub Git 快照读 当前读 视图 神经系统 矢量存储 数据库类型 AI代理 查询规划 count(*) count(主键) 行数 算法 CAS 技巧 多线程 并发控制 恢复机制 闪回