假设一个表有两列:From和To。例如:
From To
1 2
2 3
2 4
4 5
我想知道找到可以使用SQL查询从节点访问的所有节点的最有效方法。示例:给定1它将返回2,3,4和5.可以使用由UNION子句联合的多个查询,但它将限制可以达到的级别数。也许不同的数据结构会使问题更容易处理,但这是可用的。
我正在使用Firebird,但我希望有一个只使用标准SQL的解决方案。
答案 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;%'