繁体   English   中英

SQL Server中多对多层次结构的数据结构

[英]Data structure for many to many hierarchies in SQL Server

我的系统中已经有以下数据结构。

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并运行查询。 由于它具有数百万行,因此我根本无法获得输出。

我想创建一个数据结构,使其能够从上到下或从下到上(在任何节点级别)提供信息。

有人可以帮我吗?

不建议将RDBMS用于分层数据结构,这是创建图形数据库的原因。

顺便说一句闭合表模式将为您提供帮助。
闭合表解决方案是一种简单而优雅的存储层次结构的方法。 它涉及存储通过树的所有路径,而不仅仅是存储具有直接父子关系的路径。

使用该模式的关键点是必须如何填充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的新子节点,请首先插入自引用行。 然后在TreePaths中添加引用注释#5作为后代的行集的副本(包括其中#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);



UPDATE
由于您向我们展示的示例数据导致了递归循环(而不是层次结构),例如:

1 -> 3 -> 4 -> 5 -> 3 -> 4 -> 5

遵循路径枚举模式将为您提供帮助。
甲UNIX路径等/usr/local/lib/是文件系统,其中的路径枚举usr是父local ,这turn是IIb的母体。
您可以从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;

Sqlfiddle演示

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM