SQL 如何用递归查询计算组织架构的完整路径字符串
发布时间 - 2026-01-26 00:00:00 点击率:次递归查询必须使用 WITH RECURSIVE,普通 CTE 不支持;各数据库语法差异大,MySQL 8.0 需显式设递归深度并用 COALESCE 防 NULL 截断路径,SQL Server 的 hierarchyid 高效但不通用。
递归查询必须用 WITH RECURSIVE,普通 CTE 不行
PostgreSQL、SQL Server、Oracle、SQLite 3.8.3+ 和 MySQL 8.0+ 都支持递归 CTE,但语法和限制差异大。核心是 WITH RECURSIVE 关键字——漏掉 RECURSIVE 会导致语法错误(如 PostgreSQL 报错 recursive query "t" does not have a recursive term)。MySQL 8.0 要求递归必须有终止条件(比如 level
cte_max_recursion_depth 截断。
路径拼接要用字符串连接 + COALESCE 处理根节点
组织架构中根节点的 parent_id 通常为 NULL 或 0,直接用 parent_path || '/' || name 会因 NULL 导致整条路径变 NULL。必须用 COALESCE 或 CONCAT(MySQL)兜底:
SELECT id, name, CAST(name AS VARCHAR(500)) AS path
FROM orgs WHERE parent_id IS NULL
UNION ALL
SELECT o.id, o.name,
COALESCE(t.path || ' / ', '') || o.name AS path
FROM orgs o
INNER JOIN t ON o.parent_id = t.id
注意:CAST 初始路径为足够长的字符串类型,避免后续拼接时被截断(尤其 SQL Server 对 VARCHAR 默认长度敏感)。
MySQL 8.0 需显式设递归深度,且不支持反向路径生成
MySQL 默认 cte_max_recursion_depth = 100,若组织层级超深(如 200 层),查不到完整路径。需在语句前加:
SET SESSION cte_max_recursion_depth = 500;
另外,MySQL 的 CONCAT 在遇到 NULL 时返回 NULL,不能像 PostgreSQL 那样靠 || 自动跳过;必须写成:
CONCAT(COALESCE(t.path, ''), ' / ', o.name)
如果要从叶子节点向上拼路径(比如“技术部 / 后端组 / Java 小组”),MySQL 不支持从下往上递归(无类似 CONNECT BY PRIOR 的反向引用),只能先查出所有祖先再聚合,或改用应用层处理。
SQL Server 的 hierarchyid 虽快但不通用
SQL Server 提供 hierarchyid 类型,能高效存储和查询树形结构,/1/2/3/ 这种路径可直接用 .ToString() 获取,性能远超递归 CTE。但它只存在于 SQL Server,迁移成本高;而且一旦用它,就不能再用标准 SQL 的 WITH RECURSIVE 写法——二者是互斥方案。如果团队未来可能换数据库,优先用标准递归 CTE,哪怕慢一点。
路径长度和层级深度容易被低估,尤其是测试数据只有 3 层,上线后发现某部门嵌套了 12 层,cte_max_recursion_depth 或字段长度不够就直接报错或截断。留余量比事后排查更省时间。
# mysql
# oracle
# java
# session
# 后端
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
Midjourney怎样加参数调细节_Midjourney参数调整技巧【指南】
深圳网站制作平台,深圳市做网站好的公司有哪些?
Claude怎样写结构化提示词_Claude结构化提示词写法【教程】
网站制作公司哪里好做,成都网站制作公司哪家做得比较好,更正规?
如何快速完成中国万网建站详细流程?
宙斯浏览器视频悬浮窗怎么开启 边看视频边操作其他应用教程
如何在阿里云虚拟服务器快速搭建网站?
WEB开发之注册页面验证码倒计时代码的实现
如何在云指建站中生成FTP站点?
Python结构化数据采集_字段抽取解析【教程】
Python面向对象测试方法_mock解析【教程】
googleplay官方入口在哪里_Google Play官方商店快速入口指南
Laravel怎么创建自己的包(Package)_Laravel扩展包开发入门到发布
Laravel如何实现邮件验证激活账户_Laravel内置MustVerifyEmail接口配置【步骤】
微博html5版本怎么弄发语音微博_语音录制入口及时长限制操作【教程】
怎么制作一个起泡网,水泡粪全漏粪育肥舍冬季氨气超过25ppm,可以有哪些措施降低舍内氨气水平?
Android利用动画实现背景逐渐变暗
Laravel怎么为数据库表字段添加索引以优化查询
Java类加载基本过程详细介绍
最好的网站制作公司,网购哪个网站口碑最好,推荐几个?谢谢?
矢量图网站制作软件,用千图网的一张矢量图做公司app首页,该网站并未说明版权等问题,这样做算不算侵权?应该如何解决?
Laravel如何实现用户角色和权限系统_Laravel角色权限管理机制
宙斯浏览器怎么屏蔽图片浏览 节省手机流量使用设置方法
浅谈Javascript中的Label语句
如何在阿里云域名上完成建站全流程?
Laravel如何配置Horizon来管理队列?(安装和使用)
Laravel Octane如何提升性能_使用Laravel Octane加速你的应用
如何快速生成橙子建站落地页链接?
PHP怎么接收前端传的文件路径_处理文件路径参数接收方法【汇总】
如何用虚拟主机快速搭建网站?详细步骤解析
Python3.6正式版新特性预览
儿童网站界面设计图片,中国少年儿童教育网站-怎么去注册?
Laravel项目怎么部署到Linux_Laravel Nginx配置详解
昵图网官网入口 昵图网素材平台官方入口
Laravel如何配置任务调度?(Cron Job示例)
千问怎样用提示词获取健康建议_千问健康类提示词注意事项【指南】
浅析上传头像示例及其注意事项
网站设计制作书签怎么做,怎样将网页添加到书签/主页书签/桌面?
如何在云虚拟主机上快速搭建个人网站?
Laravel如何集成微信支付SDK_Laravel使用yansongda-pay实现扫码支付【实战】
Laravel中的Facade(门面)到底是什么原理
Android GridView 滑动条设置一直显示状态(推荐)
高防服务器如何保障网站安全无虞?
Laravel怎么实现模型属性的自动加密
如何挑选优质建站一级代理提升网站排名?
javascript中的数组方法有哪些_如何利用数组方法简化数据处理
再谈Python中的字符串与字符编码(推荐)
网站制作免费,什么网站能看正片电影?
网站制作大概要多少钱一个,做一个平台网站大概多少钱?
Laravel模型事件有哪些_Laravel Model Event生命周期详解

