我的系统中已经有以下数据结构。
ItemDetails
:
ID Name
--------
1 XXX
2 YYY
3 ZZZ
4 TTT
5 UUU
6 WWW
层次结构位于单独的表中(具有多对多的关系)
ItemHierarchy
:
ParentCode ChildCode
--------------------
1 2
1 3
3 4
4 5
5 3
5 6
正如您所看到的那样3是1和3的子节点。我想遍历记录,例如来自节点3的记录。
我需要编写一个存储过程并获取3的所有祖先和3的所有子节点。
您能告诉我是否有可能提取数据?如果是这样,那么哪种数据结构就可以了。
请注意,我的表包含100万条记录,其中40%有多个层次结构。
我做过' CTE'使用级别并根据层次结构递增它,但是当我们从根节点遍历到叶级节点时,我得到最大递归错误。我试过了HierarchyID'但是当节点有多个父节点时无法获得所有细节。
更新:我可以将递归限制设置为max并运行查询。由于它有数百万行,我根本无法获得输出。
我想创建一个数据结构,使其能够从上到下或从下到上(在任何节点级别)提供信息。
有人可以帮助我吗?
答案 0 :(得分:2)
建议不要使用RDBMS进行分层数据结构,而是建立graph database的原因。
BTW遵循 Closure Table 模式会对您有所帮助
Closure Table解决方案是一种存储层次结构的简单而优雅的方法。它涉及存储树中的所有路径,而不仅仅是那些具有直接父子关系的路径。
使用该模式的关键是如何填写ItemHierarchy
表格
在树中为树中的每对节点存储一行共享祖先/后代关系,即使它们在树中由多个级别分隔。还要为每个节点添加一行以引用自身
认为我们有一个简单的图表如下:
带箭头的箭头显示ItemHierarchy
表中的行:
要检索#3的后代:
SELECT c.*
FROM ItemDetails AS ID
JOIN ItemHierarchy AS IH ON ID.ID = IH.ChildCode
WHERE IH.ParentCode = 3;
检索#3的祖先:
SELECT c.*
FROM ItemDetails AS ID
JOIN ItemHierarchy AS IH ON ID.ID = IH.ParentCode
WHERE IH.ChildCode = 3;
首先插入一个新的叶节点,例如#5的新子节点 插入自引用行。然后添加一组行的副本 将注释#5作为后代引用的TreePath(包括行) 其中#5引用自身),用后代替换后代 新项目的编号: INSERT INTO ItemHierarchy(parentCode,childCode)
SELECT IH.parentCode, 8
FROM ItemHierarchy AS IH
WHERE IH.childCode = 5
UNION ALL
SELECT 8, 8;
要删除完整的子树,例如#4及其后代,请删除ItemHierarchy中引用#4的所有行作为 后代,以及引用#4中任何一个的所有行 后代作为后代:
DELETE FROM ItemHierarchy
WHERE chidCode IN (SELECT childCode
FROM ItemHierarchy
WHERE parrentCode = 4);
的更新强>
由于您向我们展示的样本数据会导致递归循环(不是层次结构),如:
1 -> 3 -> 4 -> 5 -> 3 -> 4 -> 5
以下路径枚举模式将对您有所帮助
像/usr/local/lib/
这样的UNIX路径是文件系统的路径枚举,
其中usr
是local
的父级,turn
中的父级是lib的父级。
您可以从ItemHierarchy表创建一个表或视图,并将其命名为EnumPath
:
表EnumPath(NodeCode, Path)
对于样本数据,我们将有:
要找到节点#4的祖先:
select distinct E1.NodeCode from EnumPath E1
inner join EnumPath E2
On E2.path like E1.path || '%'
where E2.NodeCode = 4 and E1.NodeCode != 4;
要查找节点#4的后代:
select distinct E1.NodeCode from EnumPath E1
inner join EnumPath E2
On E1.path like E2.path || '%'
where E2.NodeCode = 4 and E1.NodeCode != 4;