基于有序表生成层级结构并排除指定一级节点的技术需求
解决方案:基于RowNumber生成层级结构并排除指定一级节点
嘿,我来帮你搞定这个层级结构的问题!你手里的表靠Type列区分父子关系,而且RowNumber已经帮你排好了正确的顺序,现在需要生成完整的层级路径,还要把一级节点是Asia的所有行(包括它的子节点)都排除掉对吧?
先看看你给的示例数据:
| RowNumber | Type | Area | Name |
|---|---|---|---|
| 1 | 1 | Europe | Bob |
| 2 | 2 | Scotland | Bill |
| 3 | 3 | Edinburgh | Dave |
| 4 | 2 | England | Sharron |
| 5 | 3 | London | Tessa |
| 6 | 2 | Spain | Steve |
| 7 | 2 | Portugal | Carie |
| 8 | 1 | Asia | Helen |
| 9 | 2 | Thailand | John |
| 10 | 2 | Japan | Frank |
| 11 | 3 | Tokyo | Kate |
| 12 | 3 | Osaka | Brian |
| 13 | 1 | North America | Joe |
我推荐用**递归CTE(公共表表达式)**来实现,因为它处理层级关系特别方便,而且结合RowNumber的顺序可以精准找到每个节点的父节点。下面是具体的SQL方案(以SQL Server为例,其他支持递归CTE的数据库比如MySQL 8.0+、PostgreSQL都可以适配):
-- 第一步:先筛选出需要保留的行(排除Asia及其所有子节点) WITH FilteredData AS ( SELECT * FROM YourTableName -- 替换成你的实际表名 WHERE NOT ( RowNumber > (SELECT RowNumber FROM YourTableName WHERE Type=1 AND Area='Asia') AND RowNumber < (SELECT MIN(RowNumber) FROM YourTableName WHERE Type=1 AND RowNumber > (SELECT RowNumber FROM YourTableName WHERE Type=1 AND Area='Asia')) ) ), -- 第二步:递归构建完整层级结构 HierarchyCTE AS ( -- 锚点成员:所有合法的一级节点(Type=1) SELECT RowNumber, Type, Area, Name, CAST(Area AS VARCHAR(MAX)) AS FullAreaHierarchy, -- 完整区域层级路径 CAST(Name AS VARCHAR(MAX)) AS FullNameHierarchy, -- 完整名称层级路径 RowNumber AS ParentRowNumber, -- 一级节点的父节点就是自己 1 AS Level -- 层级深度 FROM FilteredData WHERE Type = 1 UNION ALL -- 递归成员:匹配子节点和对应的父节点 SELECT fd.RowNumber, fd.Type, fd.Area, fd.Name, CONCAT(hc.FullAreaHierarchy, ' > ', fd.Area) AS FullAreaHierarchy, CONCAT(hc.FullNameHierarchy, ' > ', fd.Name) AS FullNameHierarchy, -- 找到当前节点之前最近的、Type比自己小1的节点作为父节点 (SELECT TOP 1 RowNumber FROM FilteredData WHERE RowNumber < fd.RowNumber AND Type = fd.Type - 1 ORDER BY RowNumber DESC) AS ParentRowNumber, hc.Level + 1 AS Level FROM FilteredData fd JOIN HierarchyCTE hc ON (SELECT TOP 1 RowNumber FROM FilteredData WHERE RowNumber < fd.RowNumber AND Type = fd.Type - 1 ORDER BY RowNumber DESC) = hc.RowNumber WHERE fd.Type > 1 ) -- 输出最终结果,按RowNumber保持原顺序 SELECT * FROM HierarchyCTE ORDER BY RowNumber;
代码解释:
- FilteredData CTE:通过定位Asia一级节点的
RowNumber(这里是8),找到下一个一级节点的RowNumber(13),直接排除这两个值之间的所有行,这样就彻底去掉了Asia及其所有子节点。 - HierarchyCTE:
- 锚点部分先取出所有合法的一级节点,初始化层级路径和深度。
- 递归部分针对每个子节点(Type>1),通过
RowNumber的顺序找到它前面最近的、Type刚好小1的节点作为父节点,同时拼接出完整的层级路径。
如果你的数据库不支持递归CTE,也可以用临时表+循环的方式实现,但递归CTE是最简洁高效的方案。
内容的提问来源于stack exchange,提问作者Scott B
相关产品推荐
相关产品推荐

