从底部到特定级别遍历SQL层次结构

时间:2014-01-29 14:59:28

标签: sql sql-server tsql

我有一个表,我将从第三方Web服务中搜索几百个服务。这些服务有几百万个符号,我也是。

层次结构本质上就是这个;

root
|_service1
| |_service1/sub1*
| |_service1/sub2
| |_service1/sub3
| |_service1/sub4
| | |_service1/sub4/sub1
| |   |_**service1/sub4/sub1/leaf1**
| |
| |_service1/sub5
|
|_service2
  |_service2/sub1 
  |_service2/sub2
  |_service2/sub3

所以我想要实现的是 - 给一个叶子的Id,我想在树上工作直到我发现分支isActive为真然后返回该值。

在此示例中,我想查找叶/service1/sub4/sub1/leaf1的有效服务,在本例中为service1/sub1

到目前为止,我一直在使用Common Table Expression从上到下工作,并在该分支下的叶子上设置一个额外的ActiveServiceId列;数以百万计的符号变成了一个漫长的过程。

我只使用了一小部分符号(虽然我不知道哪些符号,但我需要它们)所以查询时已知的叶子ID只有几百个。 / p>

我创建了一个SQLFiddle来反映这个层次,以帮助任何可能提供帮助的人

更新进一步解释当前的方法。如果我决定将service1作为新的活动服务 - 每个子分支中service1下的叶子需要冒泡到service1,我将重置所有子分支,因此它们都没有被标记为活动

2 个答案:

答案 0 :(得分:1)

您可能会发现使用嵌套集存储此数据很有用:

http://en.wikipedia.org/wiki/Nested_set_model

我之前使用过这种方法将树数据存储在数据库中,发现它可以查询属于父级等所有节点的数据。

使用存储在嵌套集中的数据,您的问题的解决方案如下:

SELECT s.ID
FROM TreeTable s
WHERE s.L = (SELECT Max(t.L)
            FROM TreeTable t, TreeTable LeafNode
            WHERE t.isActive = true
              AND t.L < LeafNode.L
              AND t.R > LeafNode.R
              AND LeafNode.ID = ?)

答案 1 :(得分:0)

如果您将完整路径存储为每个节点的字符串,则可以执行以下操作:

SELECT r.ID
FROM TreeTable r, TreeTable rs
WHERE rs.ID = ?
  AND r.Path = Left(rs.path,Len(r.Path))
  AND Len(r.Path) = (SELECT Max(Len(t.Path))
                     FROM TreeTable t, TreeTable s
                     WHERE s.ID = ?
                       AND t.Path = Left(s.path,Len(t.Path))
                       AND t.isActive = true)

好吧,它不漂亮,我欢迎任何使它更整洁的建议 - 但它应该有用。