处理数据库中的层次结构数据

Rya*_*ott 7 sql hierarchical-data

我很想知道处理层次结构的最佳方法(最佳实践)是关于数据库设计的.这是我通常如何处理它们的一个小例子.

节点表

NodeId int PRIMARY KEY
NodeParentId int NULL
DisplaySeq int NOT NULL
Title nvarchar(255)
Run Code Online (Sandbox Code Playgroud)

祖先表

NodeId int
AncestorId int
Hops int
Run Code Online (Sandbox Code Playgroud)

使用NodeId上的索引,AncestorId,Hops

表格如下所示:

节点表

NodeId    NodeParentId    DisplaySeq    Title
1         NULL            1             'Root'
2         1               1             'Child 1'
3         1               2             'Child 2'
4         2               1             'Grandchild 1'
5         2               2             'Grandchild 2'
Run Code Online (Sandbox Code Playgroud)

祖先表

NodeId    AncestorId    Hops
1         NULL          0
1         1             0
2         1             1
2         2             0
3         1             1
3         3             0
4         1             2
4         2             1
4         4             0
5         1             2
5         2             1
5         5             0
Run Code Online (Sandbox Code Playgroud)

通过这种设计,我发现使用大型层次结构,通过连接AncestorId = target NodeId的Ancestor表,可以非常快速地获得层次结构的整个部分,如:

SELECT *
FROM Node n
INNER JOIN Ancestor a on a.NodeId=n.NodeId
WHERE a.AncestorId = @TargetNodeId
Run Code Online (Sandbox Code Playgroud)

这也很容易让直接的孩子

SELECT *
FROM Node n
INNER JOIN Ancestor a on a.NodeId=n.NodeId
WHERE a.AncestorId = @TargetNodeId
AND Hops = 1
Run Code Online (Sandbox Code Playgroud)

我很想知道你可能用过的其他解决方案是什么类型的东西.根据我的经验,层次结构可能非常繁琐,任何优化检索的方法都非常重要.

n8w*_*wrl 10

有一些特定于供应商的扩展可以做到这一点,但我最喜欢的db-neutral方式来自Joe Celko - 谷歌'Joe Celko Trees and Hierarchies'或者购买这本书:链接文本

这是一个非常聪明的基于集合的方式.易于查询层次结构.我添加了'parentID'字段,因为我问了'直接孩子'和'父母'问题,并加快了这些问题.但这是一种获得'祖先'或'descdent'查询的好方法.


Mar*_*usQ 6

您可能还想查看"嵌套集"模式:

http://www.intelligententerprise.com/001020/celko.jhtml(Broken Link)

或者你可以谷歌更多.

PS:诅咒,n8wrl,你输的比我快!


Tom*_*m H 4

正如 MarkusQ 和 n8wrl 已经指出的那样,Joe Celko 在这方面有一些好东西。我只想补充一点,有多种方法可以对层次结构进行建模(乔的书中包含了几种我认为的方法,而不仅仅是他认为“最好”的方法)。您的最终决定将希望考虑到您自己的具体需求。一些不同的建模方法更适合写入密集型操作,而另一些则更适合在层次结构中上下频繁或快速读取。只需记住您的系统将用它做什么。