使用SQL查找所有可访问的节点

时间:2010-09-20 19:42:01

标签: sql data-structures tree firebird

假设一个表有两列:From和To。例如:

From To
1    2
2    3
2    4
4    5

我想知道找到可以使用SQL查询从节点访问的所有节点的最有效方法。示例:给定1它将返回2,3,4和5.可以使用由UNION子句联合的多个查询,但它将限制可以达到的级别数。也许不同的数据结构会使问题更容易处理,但这是可用的。

我正在使用Firebird,但我希望有一个只使用标准SQL的解决方案。

3 个答案:

答案 0 :(得分:8)

如果你使用大多数品牌的数据库,你可以使用recursive common table expression - 除了MySQL和SQLite以及其他一些不起眼的数据库(对不起,我确实认为Firebird模糊不清)。此语法是ANSI SQL标准,但Firebird 尚不支持它。

更正: Firebird 2.1确实支持递归CTE,正如@Hugues Van Landeghem评论的那样。

否则请参阅我的演示文稿Models for Hierarchical Data with SQL以了解几种不同的方法。

例如,您可以为树中的每个路径存储其他行,而不仅仅是直接的父/子路径。我将此设计称为 Closure Table

From To   Length
1    1    0
1    2    1
1    3    2
1    4    2
1    5    3
2    2    0
2    3    1
2    4    1
3    3    0
4    4    0
4    5    1
5    5    0

现在您可以查询SELECT * FROM MyTable WHERE From = 1并获取该节点的所有后代。

PS:我会避免命名列From,因为这是一个SQL保留字。

答案 1 :(得分:1)

不幸的是,没有一个好的通用解决方案可以适用于所有数据库的所有情况。

我建议您查看这些资源以获取MySQL解决方案:

对于PostgreSQL和SQL Server,您应该查看recursive CTEs

如果您使用的是Oracle,那么您应该查看CONNECT BY这是SQL的专有扩展,它可以更轻松地处理树结构。

答案 2 :(得分:0)

使用标准SQL,存储具有可接受读取性能的树的唯一方法是使用路径枚举等hack。请注意,这在写入时非常繁重。

ID   PATH
1    1
2    1;2
3    1;2;3
4    1;2;4


SELECT * FROM tree WHERE path LIKE '%2;%'