SQL语句中实现递归查询操作方法

 更新时间:2026年05月22日 09:33:44   作者:rchmin  
这篇文章给大家介绍SQL语句中实现递归查询操作方法,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧

在SQL中实现递归查询操作,通常有两种主要的方法:使用递归公用表表达式(Recursive Common Table Expressions,CTEs)和递归查询函数(例如,在PostgreSQL中使用WITH RECURSIVE,在SQL Server中使用WITH RECURSIVECTE,而在Oracle中使用CONNECT BY)。

数据表定义:

CREATE TABLE employees (
    id INT PRIMARY KEY,
    name VARCHAR(50),
    manager_id INT  -- 指向上级,CEO的manager_id为NULL(或0,通常用NULL表示无上级)
);

初始化数据:

INSERT INTO `employees` (`id`, `name`, `manager_id`) VALUES (101, '马总', NULL);
INSERT INTO `employees` (`id`, `name`, `manager_id`) VALUES (201, '张工', 101);
INSERT INTO `employees` (`id`, `name`, `manager_id`) VALUES (202, '王工', 101);
INSERT INTO `employees` (`id`, `name`, `manager_id`) VALUES (301, '李工', 201);
INSERT INTO `employees` (`id`, `name`, `manager_id`) VALUES (401, '赵工', 301);
INSERT INTO `employees` (`id`, `name`, `manager_id`) VALUES (402, '刘工', 301);

查询需求:

请查询出id=101的人员及其所有的下级信息(包括间接下级),同时标记出下属层级,自身层级设为0;

查询语句(MySQL 8.0+):

要查询 id = 101 的所有下级(包括直接和间接下级),并标记出每个下属所处的层级(1 表示直接下级,2 表示下级的下级,依此类推),可以使用递归公用表表达式(Recursive CTE)。以下是符合要求的 SQL 语句:

WITH RECURSIVE subordinates AS (
    -- 初始查询:找到直接下级(manager_id = 101)
    SELECT 
        id,
        name,
        manager_id,
        0 AS level
    FROM employees
    WHERE id = 101
    UNION ALL
    -- 递归查询:找到下一级下属
    SELECT 
        e.id,
        e.name,
        e.manager_id,
        s.level + 1
    FROM employees e
    INNER JOIN subordinates s ON e.manager_id = s.id
)
SELECT *
FROM subordinates
ORDER BY level, id;

执行结果:

语法解释:

WITH RECURSIVE subordinates AS (...) 是 SQL 中用于定义递归公用表表达式(Recursive Common Table Expression)的语法。下面逐部分解释:

1.WITH关键字

  • 表示定义一个公用表表达式(CTE,Common Table Expression),类似于一个临时的命名结果集,可以在后续的查询中引用。
  • 通常用于简化复杂查询,提高可读性。

2.RECURSIVE关键字

  • 指明该 CTE 是递归的,即它可以在自己的定义中引用自身,从而实现迭代或层次遍历。
  • 大部分主流数据库(如 PostgreSQL、MySQL 8.0+、SQL Server、Oracle)都支持该语法,但 MySQL 中必须明确写出 RECURSIVE,而 SQL Server 中可省略(但需要其他方式表示递归)。

3.subordinates– CTE 名称(自定义)

  • 给这个临时结果集取名为 subordinates,后续的 SELECT 语句就可以像使用普通表一样使用它。

4. 括号内的递归定义

递归 CTE 通常由两部分组成,用 UNION ALL 连接:

(1)锚点成员(非递归部分)

SELECT id, name, manager_id, 1 AS level
FROM employees
WHERE id = 101
  • 这是递归的起点,首先查询出 id = 101 的员工(即 101 自身)。
  • 这里手动标记 level = 0,表示第 0 层级。
  • 锚点成员只执行一次,其结果集作为递归的初始数据。

(2)递归成员(递归部分)

SELECT e.id, e.name, e.manager_id, s.level + 1
FROM employees e
INNER JOIN subordinates s ON e.manager_id = s.id
  • 递归成员会反复执行,直到不再返回新行。
  • 每次迭代中,它只将上一轮 subordinates 结果集中的每一行(作为上级 s)与 employees 表连接,找出这些上级的下级员工(e.manager_id = s.id)。
  • 同时,层级别为 s.level + 1,表示比上一级深一层。
  • 新找到的行被加入 subordinates 结果集,并用于下一次迭代。

(3) 终止条件

  • 当某次迭代没有产生任何新行时,递归自动停止。
  • 要求数据中没有循环引用(例如 A 的上级是 B,B 的上级又是 A),否则可能导致无限递归。大多数数据库默认设置了递归深度限制(如 MySQL 的 cte_max_recursion_depth)。

5. 最终引用

定义完 subordinates 后,外层的 SELECT * FROM subordinates 将返回所有递归收集到的行。

示例执行流程

假设 employees 表有数据:

  • id=101 管理 201,202
  • 201 管理 301
  • 301 管理 401,402

执行过程:

  • 锚点:找到 201、202,level=1。
  • subordinates 当前有 (201, ..., 1), (202, ..., 1)。
  • 第一次递归:以 201、202 为上级找下级 → 找到 301(上级 201),level=2。
  • subordinates 新增 (301, ..., 2)。
  • 第二次递归:以 301 为上级找下级 → 找到 401,402,level=3。
  • subordinates 新增 (401, ..., 3),(402, ..., 3)。
  • 第三次递归:以 401、402 为上级找下级 → 无结果,终止。
  • 最终输出所有行。

适用场景

  • 组织架构(上级-下级)
  • 物料清单(BOM)
  • 树形结构遍历(评论回复、分类层级)
  • 图或路径查询

WITH RECURSIVE 是处理此类分层或递归查询的标准 SQL 方法,比使用游标或多次自连接更加简洁高效。

到此这篇关于SQL语句中如何实现递归查询操作的文章就介绍到这了,更多相关SQL递归查询内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SQL学习笔记一SQL基础知识

    SQL学习笔记一SQL基础知识

    刚开始接触sqlserver的朋友可以参考下。虽然文字比较短,但内容都是经验之谈。
    2011-08-08
  • 一个简单的SQL 行列转换语句

    一个简单的SQL 行列转换语句

    在数据库开发中经常会遇到行列转换的问题,比如下面的问题,部门,员工和员工类型三张表,我们要统计类似这样的列表
    2009-08-08
  • SQL实现筛选出连续3天登录用户与窗口函数的示例代码

    SQL实现筛选出连续3天登录用户与窗口函数的示例代码

    本文主要介绍了SQL实现筛选出连续3天登录用户与窗口函数的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-04-04
  • Sql注入工具_动力节点Java学院整理

    Sql注入工具_动力节点Java学院整理

    这篇文章主要为大家详细介绍了Sql注入工具的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-08-08
  • SQL查询中按多个字段排序的方法

    SQL查询中按多个字段排序的方法

    本文主要介绍了SQL查询中按多个字段排序的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-07-07
  • SQL Server 2008 R2数据库迁移的实现方法

    SQL Server 2008 R2数据库迁移的实现方法

    这篇文章给大家介绍了SQL Server 2008 R2数据库迁移的两种方案简要指南,文章通过图文结合介绍的非常详细,对大家的学习或工作有一定的帮助,需要的小伙伴跟着小编一起来看看吧
    2024-01-01
  • sql server学习基础之内存初探

    sql server学习基础之内存初探

    这篇文章主要给大家介绍了关于sql server中内存的相关资料,文中通过图文以及示例代码介绍的非常详细,对大家学习或者理解sql server具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-07-07
  • SQL Server表空间碎片化回收的实现

    SQL Server表空间碎片化回收的实现

    本文主要介绍了SQL Server表空间碎片化回收的实现,文中根据实例编码详细介绍的十分详尽,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • SQLServer数据库如何还原重命名

    SQLServer数据库如何还原重命名

    这篇文章主要介绍了SQLServer数据库如何还原重命名问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-06-06
  • sqlserver性能优化之内存优化详解

    sqlserver性能优化之内存优化详解

    本文介绍了SQL Server内存优化的详细方案,包括核心配置、监控手段和高级技术,并提供了脚本示例及配置建议,内容涵盖了内存上下限设置、启用AWE、缓冲池扩展、监控关键内存指标、清理缓存策略、索引优化、内存优化表(In-Memory OLTP)以及自动化维护与监控等
    2026-03-03

最新评论