如何获取树形路径结果集?附数据表结构与预期结果
如何生成树形结构的层级路径(如Master/Employee/Leave)?
先明确你的需求:
原始数据表
ID Name ParentID 1 Master 0 2 Employee 1 3 Leave 2 4 Admin 1 期望生成带层级路径的结果
ID Name ParentID Result 1 Master 0 Master 2 Employee 1 Master/Employee 3 Leave 2 Master/Employee/Leave 4 Admin 1 Master/Admin
这是很常见的树形结构遍历需求,核心是通过递归查询拼接父节点到当前节点的名称,下面分不同数据库给出实现方案:
方案1:SQL Server / PostgreSQL(支持递归CTE)
递归CTE是最简洁高效的方式,直接遍历树形结构拼接路径:
WITH RecursiveCTE AS ( -- 锚点:先取出所有根节点(ParentID=0) SELECT ID, Name, ParentID, CAST(Name AS VARCHAR(MAX)) AS Result FROM YourTableName WHERE ParentID = 0 UNION ALL -- 递归:关联父节点,把当前节点名称拼接到父路径后面 SELECT t.ID, t.Name, t.ParentID, CAST(r.Result + '/' + t.Name AS VARCHAR(MAX)) AS Result FROM YourTableName t INNER JOIN RecursiveCTE r ON t.ParentID = r.ID ) SELECT * FROM RecursiveCTE ORDER BY ID;
方案2:MySQL 8.0+(支持递归CTE)
MySQL 8.0及以后版本也支持递归CTE,语法和上面类似:
WITH RECURSIVE RecursiveCTE AS ( SELECT ID, Name, ParentID, Name AS Result FROM YourTableName WHERE ParentID = 0 UNION ALL SELECT t.ID, t.Name, t.ParentID, CONCAT(r.Result, '/', t.Name) AS Result FROM YourTableName t JOIN RecursiveCTE r ON t.ParentID = r.ID ) SELECT * FROM RecursiveCTE ORDER BY ID;
方案3:MySQL 5.x(不支持递归CTE)
如果你的MySQL版本比较旧,没法用递归CTE,可以写一个自定义函数来实现路径拼接:
DELIMITER // CREATE FUNCTION GetHierarchyPath(nodeID INT) RETURNS VARCHAR(255) DETERMINISTIC BEGIN DECLARE path VARCHAR(255); DECLARE parentNodeID INT; DECLARE parentName VARCHAR(255); -- 初始化路径为当前节点名称 SET path = (SELECT Name FROM YourTableName WHERE ID = nodeID); SET parentNodeID = (SELECT ParentID FROM YourTableName WHERE ID = nodeID); -- 循环向上查找父节点,直到根节点(ParentID=0) WHILE parentNodeID != 0 DO SET parentName = (SELECT Name FROM YourTableName WHERE ID = parentNodeID); SET path = CONCAT(parentName, '/', path); SET parentNodeID = (SELECT ParentID FROM YourTableName WHERE ID = parentNodeID); END WHILE; RETURN path; END // DELIMITER ; -- 调用函数查询结果 SELECT ID, Name, ParentID, GetHierarchyPath(ID) AS Result FROM YourTableName ORDER BY ID;
注意事项
- 记得把代码里的
YourTableName替换成你实际使用的表名 - 如果你的名称字段长度比较长,要调整字符串类型的长度(比如SQL Server用
VARCHAR(MAX),MySQL可以把VARCHAR(255)改成更大的值) - 确保你的树形结构没有循环引用(比如子节点的ParentID指向自己或者上层节点形成环),否则递归会无限循环,SQL Server默认有100层的递归限制,必要时可以用
OPTION (MAXRECURSION 0)取消限制,但不建议这么做除非你确认没有循环。
内容的提问来源于stack exchange,提问作者Ranjith S




