简短的回答:没有。
这是一个 SQLFiddle,演示了我在评论中描述的问题。
对于这个简单的设置:
id, path
1, '1'
2, '1\2'
3, '1\3'
4, '1\4'
5, '1\5'
6, '1\6'
7, '1\7'
8, '1\8'
9, '1\9'
10, '1\10'
尝试id = 10
使用简单排序获取最右边的叶子 ( ) 将失败:
SELECT TOP 1
id,
path
FROM hierarchy
ORDER BY path DESC
返回:
id, path
9, 1\9
因为path
是基于文本的列,所以1\10
会排在降序之后(参见小提琴中第二个查询的结果)。 1\9
即使您开始跟踪通常便宜且易于跟上的深度和路径长度,也完全有可能获得如下路径:
path depth length
12\3\11\2 4 9
5\17\10\1 4 9
仍然无法正确排序。
即使您使用字母而不是数字,这也只会将问题范围推到第 26 个孩子而不是第 10 个孩子:
SQLFiddle 使用字母
我对物化路径操作不像我对嵌套集和邻接列表那样熟悉,并且没有使用 django 的经验,所以如果有我不知道的方法,我会遵从其他人,但你几乎肯定必须对列执行某种解析path
以始终获得正确的叶子。
编辑 - 解决了排序是否是有效解决方案的问题后,在经过一些讨论和思考问题后,这里有一些关于其他潜在解决方案的附加说明:
- 当节点可以有两个以上的子节点时,“最右边”是一个模糊的术语(即,树不是二叉树)。如果一个节点有 10 个子节点,哪些在父节点的左边,哪些在右边?您必须先定义此条件,然后才能定义问题的解决方案。
-一旦为您的问题空间正确定义了“最右边”,请了解最右边的节点不一定位于树的最低级别:
1
/ \
1\1 1\2 <= This is the rightmost node
/
1\1\1 <= This is the lowest node
-一旦定义了“最右边”,就可以使用一个简单的循环以编程方式找到最右边的节点:
//in pseudocode
function GetRightmostNode(Node startNode)
{
Node currentNode = startNode;
while(currentNode.RightChildren != null)
{
currentNode = maximum of currentNode.RightChildren;
}
return currentNode;
}
此循环将在当前节点右侧查找当前节点的子节点。如果它们存在,它会选择最右边的正确的孩子并重复。一旦它到达右边没有子节点的节点,它就会返回当前节点,因为它找到了树(或子树)的最右边节点startNode
作为其根。