我很想知道处理层次结构的最佳方法(最佳实践)是关于数据库设计的。这是我通常如何处理它们的一个小例子。
节点表
NodeId int PRIMARY KEY
NodeParentId int NULL
DisplaySeq int NOT NULL
Title nvarchar(255)
Ancestor Table
NodeId int
AncestorId int
Hops int
在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'
Ancestor Table
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
通过这种设计,我发现对于大型层次结构,我可以通过连接AncestorId = target NodeId的Ancestor表来非常快速地获得层次结构的整个部分,如:
SELECT *
FROM Node n
INNER JOIN Ancestor a on a.NodeId=n.NodeId
WHERE a.AncestorId = @TargetNodeId
也可以轻松获得直接的孩子
SELECT *
FROM Node n
INNER JOIN Ancestor a on a.NodeId=n.NodeId
WHERE a.AncestorId = @TargetNodeId
AND Hops = 1
我很想知道您可能已经使用过哪种其他解决方案。根据我的经验,层次结构可能非常繁琐,任何优化检索的方法都非常重要。
答案 0 :(得分:10)
有一些供应商特定的扩展可以做到这一点,但我最喜欢的db-neutral方式来自Joe Celko - 谷歌'Joe Celko树和层次结构'或者购买这本书:link text
这是一个非常聪明的基于集合的方式。易于查询层次结构。我添加了'parentID'字段,因为我问了'直接孩子'和'父母'问题,并加快了这些问题。但这是一种获得'祖先'或'descdent'查询的好方法。
答案 1 :(得分:6)
您可能还想查看“嵌套集”模式:
http://www.intelligententerprise.com/001020/celko.jhtml (Broken Link)
或者你可以谷歌了解更多。
P.S。:诅咒,n8wrl,你输入的速度比我快!
答案 2 :(得分:4)
正如MarkusQ和n8wrl已经指出的那样,Joe Celko对此有一些好处。我只想补充说,有多种方法可以建立一个层次结构(Joe的书中包含了几个我相信的,而不仅仅是他认为是“最好的”)。您的最终决定有望考虑到您自己的特定需求。对其进行建模的一些不同方法对于写入密集型操作更好,而对于频繁或快速读取层次结构的其他方式则更好。请记住您的系统将使用它做什么。
答案 3 :(得分:2)
SQL Server 2008引入了hierarchyid data type
答案 4 :(得分:1)
在Oracle中,您可以使用CONNECT BY / START WITH来查询分层数据。 在SQL Server中,您可以使用以递归方式调用自身的存储过程。
答案 5 :(得分:1)