我们使用具有名为docid的列和名为parentid的列的表来存储Oracle数据库中的文档之间的关系.如果我有一个与子文档相关的文档doc1,child1_1和child1_2,它们将由Documents表中的以下记录表示.
docid parentid
1000 null record for doc1
1001 1000 " " child1_1
1002 1000 " " child1_2
Run Code Online (Sandbox Code Playgroud)
Documents表可以包含数百万行,因此为了确保所有相关文档在我们的UI中组合在一起,我们使用名为sortedfamily的索引varchar列对Documents表进行预排序,并使用相关文档的docids的连接对其进行填充. .如果不使用sortedfamily列,则在查询时对记录进行排序太慢.上面显示的记录成为.
docid parentid sortedfamily
1000 null 1000 record for doc1
1001 1000 1000_1001 " " child1_1
1002 1000 1000_1002 " " child1_2
Run Code Online (Sandbox Code Playgroud)
这允许我们将"ordered by sortedfamily"添加到我们的查询中,并且返回的记录将始终按相关文档排序.我上面概述的工作非常好,但它有一些与文档族层次深度相关的限制,并且感觉奇怪的连接整数来对记录进行排序.有没有办法只使用整数执行上述操作?
提前致谢.
更新:我上面的例子不够详细.孩子们自己也可能有相关文件.如果child1_1具有相关文档,则sortedfamily的结果值可能是"1000_1001_2000".
Oracle对分层查询提供了出色的支持.您可以在不依赖sortedfamily列的情况下获取文档层次结构.这是查询:
SELECT docid, PRIOR docid AS "Parent"
FROM Documents
START WITH parentid IS NULL
CONNECT BY parentid = PRIOR docid
ORDER SIBLINGS BY docid
Run Code Online (Sandbox Code Playgroud)
现在解释一下:
SELECT docid, PRIOR docid AS "Parent"
Run Code Online (Sandbox Code Playgroud)
这通过"回顾" PRIOR操作符使文档及其父级在同一行上.
START WITH parentid IS NULL
Run Code Online (Sandbox Code Playgroud)
这定义了层次结构的根.每个具有null的行都parentid被视为分支的根.
CONNECT BY parentid = PRIOR docid
Run Code Online (Sandbox Code Playgroud)
这表示当前行的"父级"由parentid子级连接到docid父级.
ORDER SIBLINGS BY docid
Run Code Online (Sandbox Code Playgroud)
这将按整个层次结构排序,而不是单个值.这很难解释,但它确实有效.
关于Oracle分层查询的最好的事情是它们将查询整个分支,所以如果你有一个孩子的文档有一个孩子(有一个孩子,并且......),Oracle会处理它.它还将处理每个父母的多个孩子.
这里有一个SQL小提琴,包含您的数据和一些其他文档.
小提琴还包括一个列,该列使用该SYS_CONNECT_BY_PATH函数显示整个"根到分支"的关系.在SYS_CONNECT_BY_PATH做同样的事情为你sortedfamily列,但它确实是动态的,无需维护的列.这也是可视化层次结构的每个分支的好方法.
附录
请注意,上面的查询将返回每个文档的每个分支.如果您只对单个文档感兴趣,请将其替换为:docid = 1000START WITH parentid IS NULL
START WITH docid = 1000
Run Code Online (Sandbox Code Playgroud)
那将为你提供docid1000 的整个分支.如果你有一个索引docid就会非常快.