SQL怎样在MySQL中实现递归查询_使用WITH RECURSIVE公用表

来源:PHP编程网作者:长沙GEO公司头衔:草根站长
导读:本期聚焦于小伙伴创作的《SQL怎样在MySQL中实现递归查询_使用WITH RECURSIVE公用表》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《SQL怎样在MySQL中实现递归查询_使用WITH RECURSIVE公用表》有用,将其分享出去将是对创作者最好的鼓励。

在MySQL8.0版本之前,要实现递归查询层级数据,比如查询某个部门下的所有子部门、某个分类下的所有子分类,往往需要编写复杂的存储过程或者多层自连接语句,实现成本高且可读性差。MySQL8.0引入的WITH RECURSIVE公用表表达式语法,让递归查询的实现变得简单直观,只需要按照固定语法结构编写语句就能完成层级数据的遍历查询。

SQL怎样在MySQL中实现递归查询_使用WITH RECURSIVE公用表

WITH RECURSIVE基本语法结构

WITH RECURSIVE的完整语法由两部分组成,分别是递归锚点部分和递归部分,两部分通过UNION ALL或者UNION连接,基本结构如下:

WITH RECURSIVE 公用表名称 (列1, 列2, ...) AS (
    -- 锚点部分:查询初始层级数据,也就是递归的起点
    SELECT 列1, 列2, ...
    FROM 表名
    WHERE 初始条件
    UNION ALL
    -- 递归部分:基于上一次查询的结果,继续查询下一层级数据
    SELECT 表别名.列1, 表别名.列2, ...
    FROM 公用表名称 递归别名
    INNER JOIN 表名 表别名 ON 递归别名.关联列 = 表别名.父级关联列
)
SELECT * FROM 公用表名称;

其中锚点部分只会执行一次,用来获取递归的初始数据集,递归部分会反复执行,直到没有新的数据返回为止,整个递归过程才会结束。

实际场景示例:查询部门所有下属部门

假设我们有一个部门表dept,表结构如下:

字段名类型说明
idINT部门ID,主键
dept_nameVARCHAR(50)部门名称
parent_idINT父部门ID,顶级部门该值为NULL

现在需要查询id为1的部门下的所有子部门,包括间接下属部门,使用WITH RECURSIVE的实现代码如下:

-- 创建测试表并插入测试数据
CREATE TABLE dept (
    id INT PRIMARY KEY,
    dept_name VARCHAR(50),
    parent_id INT
);

INSERT INTO dept VALUES
(1, '总公司', NULL),
(2, '技术部', 1),
(3, '产品部', 1),
(4, '前端组', 2),
(5, '后端组', 2),
(6, '设计组', 3);

-- 递归查询id为1的部门的所有下属部门
WITH RECURSIVE sub_dept AS (
    -- 锚点部分:查询初始部门,也就是id为1的部门
    SELECT id, dept_name, parent_id
    FROM dept
    WHERE id = 1
    UNION ALL
    -- 递归部分:关联查询子部门
    SELECT d.id, d.dept_name, d.parent_id
    FROM sub_dept sd
    INNER JOIN dept d ON sd.id = d.parent_id
)
SELECT * FROM sub_dept;

执行上述查询后,会返回id为1的总公司,以及其下属的技术部、产品部,还有技术部下属的前端组、后端组,产品部下属的设计组,所有层级的部门都会被查询出来。

递归查询的注意事项

  • 递归部分必须使用UNION ALL,如果使用UNION会自动去重,会增加额外的性能开销,除非明确需要去重,否则优先使用UNION ALL
  • 递归查询必须有终止条件,也就是递归部分最终查询不到新的数据,否则会出现无限递归的错误,MySQL默认会限制递归深度,也可以通过cte_max_recursion_depth参数调整最大递归深度。
  • 锚点部分和递归部分查询的列数量和数据类型必须完全一致,否则语句会执行失败。
  • 递归公用表表达式不能在递归部分引用自身多次,也不能在递归部分使用GROUP BYHAVINGORDER BY等聚合相关的子句,除非是在子查询中使用。

性能优化建议

如果递归查询的数据量比较大,建议在关联字段上建立索引,比如上述示例中的parent_id字段,建立索引可以加快递归过程中关联查询的速度。另外尽量避免递归过深的查询,如果层级过多可以考虑调整数据结构,比如增加冗余的层级字段来避免递归查询。

需要注意的是,WITH RECURSIVE是MySQL8.0及以上版本才支持的语法,如果是低于8.0的版本,无法使用该语法实现递归查询,只能通过其他方式替代。

MySQL递归查询WITH_RECURSIVE公用表表达式修改时间:2026-07-04 17:21:27

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。