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

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

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

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