SQL Server - 如何管理表中的分层数据?
我使用 SQL Server 2000。
假设我有两个如下所示的表:
Area
----------------------------------
ID| Name | HierarchyLevel
----------------------------------
1 | World | 1
2 | America| 2
3 | Europe | 2
4 | Africa | 2
5 | USA | 3
AreaHierarchy.ParentID
AreaHierarchy
------------------------
ID | ParentID | ChildID
------------------------
1 | 1 | 2
2 | 1 | 3
3 | 1 | 4
4 | 2 | 5
其中
和 AreaHierarchy.ChildID 是 Area.ID 的 FK
我怎样才能找到 USA 的第 n 个父级?
不循环可以吗?
可能不会。
I use SQL Server 2000.
Suppose I have two tables like the following:
Area
----------------------------------
ID| Name | HierarchyLevel
----------------------------------
1 | World | 1
2 | America| 2
3 | Europe | 2
4 | Africa | 2
5 | USA | 3
and
AreaHierarchy
------------------------
ID | ParentID | ChildID
------------------------
1 | 1 | 2
2 | 1 | 3
3 | 1 | 4
4 | 2 | 5
where
AreaHierarchy.ParentID and AreaHierarchy.ChildID are FKs of Area.ID
How can I find the nth parent of USA?
Is it possible without looping?
Probably not.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
没有循环,没有递归
最好的办法是在第二个表中添加附加字段,该字段将被称为 ie。
Parents
并且只需将父 ID 存储在字符串中,例如:这样您就可以轻松访问分支中的任何父级,而无需递归或任何其他复杂的过程。处理成本非常小,您只需复制父项的
Parents
值并再添加一个 ID。由于您可能需要读取的内容多于写入/更新的内容,因此这是解决您的问题的最佳解决方案。如果我是你,我只会为你拥有的数据保留一张表。将两个表合并为一个表。级别也可以根据
Parents
varchar 值中的斜杠计数来计算,但我不建议这样做。您应该注意的其他“问题”
如果您的数据主要是读/写,更新较少,那么这种结构确实非常高效。但是,如果您的表执行的更新次数多于读/写次数,则应避免使用此技术。为什么?想象一下,你有一棵很深的树,里面有很多孩子。更改根附近某个较高节点的父节点意味着您应该更新整个子树节点的父节点。
No loops, no recursion
The best thing is to add additional field in your second table, that would be called ie.
Parents
and would simply store parent IDs in a string like:This way you can easily get to any parent in the branch without recursion or any other complicated procedure. The cost in processing is very small you just copy parent's
Parents
value and add one more ID. And since you probably need to read more than write/update, this is the best solution to your problem.And if I were you, I'd just keep one table for the data you have. Join both tables into one. Level could also be computed based on counting slashes in
Parents
varchar value but I wouldn't recommend doing that.Additional 'catch' you should be aware of
If your data is mostly reads/writes and much less updates, this structure is really performant. But if your table does a lot more updates than read/writes, you should avoid this technique. Why? Imagine you have a very deep tree with lots of children. Changing a parent of some node high up in near the root would mean you should update
Parents
of the whole subtree nodes.应该有效
调用
返回 1 表示“世界”(第二个父级),调用
返回 2 表示“美国”(第一个父级)。
希望有帮助
Should work
Calling
returns 1 which means "World" (2nd parent), calling
return 2, which means "America" (1st parent).
Hope it helps
您可以使用递归。如果您有 SQL Server 2005 或更高版本,则可以使用公用表表达式。如果不是,您实际上需要使用用户定义的函数。
执行此操作的 UDF 示例可能是...
使用公共表表达式的示例可能是...
You could use recursion. If you have SQL Server 2005 or newer you can use Common Table Expressions. If not you realistically need to use User Defined Functions.
An example of a UDF to do that could be...
An example using Common Table Experessions could be...
在 SQL Server 2005+ 中,您可以在函数中使用 CTE:
In SQL Server 2005+, you'd use a CTE in a function:
我知道您希望支持 SQL Server 2000,但我认为应该注意的是,SQL Server 2008 层次结构 ID 函数 GetAncestor() 正是您所寻找的。
I understand that you want support back to SQL Server 2000, but I think it should be noted that the SQL Server 2008 Hierarchy ID function GetAncestor() does exactly what you're looking for.
您可以使用 Joe Celko 的嵌套集合模型 https://en.wikipedia.org/wiki/Nested_set_model
甚至更好的闭包表模型
You can use the nested set model by Joe Celko https://en.wikipedia.org/wiki/Nested_set_model
or even better The closure Table model