我有两张桌子。
一个列出了大约60个带有id的根文件夹,在本例中为“docnumber”。
另一个表中有大约260万行由文件夹组成 并且每个文件的ID都是“docnumber”。每行的类型为F或D,具体取决于它是文档还是文件夹。
根表
docnumber,name
100,测试
200,anothertest
文件夹/文件表
type,parentnumber,docnumber,name
D,500,600,testdoc
F,300,500,testfolder
F,200,300,testsubfolder
如何在文件夹/文档表中浏览D类的每一行,并添加一个名为TopLevelFolder的字段,该字段将从该根文档中选择该文档的顶级文件夹?它需要通过所有文件夹级别才能从根表中找到顶级文件夹。
非常感谢!
答案 0 :(得分:1)
基本上,您只需要一个递归CTE来组装层次结构树,并且需要一个排名函数来标记顶层。
;WITH Hierarchy AS(
SELECT ParentNumber, DocNumber, 1 Tier
FROM FolderDocument
WHERE [Type] = 'D'
UNION ALL
SELECT fd.ParentNumber, h.DocNumber, h.Tier + 1
FROM FolderDocument fd
INNER JOIN Hierarchy h
ON fd.DocNumber = h.ParentNumber
WHERE fd.ParentNumber IS NOT NULL
)
,HierarchyRank AS(
SELECT *, RANK() OVER (
PARTITION BY h.DocNumber ORDER BY h.Tier DESC) RankNum
FROM Hierarchy h
)
SELECT hr.DocNumber, hr.ParentNumber AS TopFolderNumber, fdd.Name AS DocName, fdf.Name AS TopFolderName
FROM HierarchyRank hr
LEFT JOIN FolderDocument fdd
ON hr.DocNumber = fdd.DocNumber
LEFT JOIN FolderDocument fdf
ON hr.ParentNumber = fdf.DocNumber
WHERE RankNum = 1
请注意,此将返回多个顶级文件夹(如果存在)。如果要实现打破平局,请将RANK()函数更改为ROW_NUMBER()并使用OVER中的ORDER BY子句指定确定“获胜者”的顺序。
此解决方案还假定FolderDocument包含树的顶级节点(它们本身具有空父项)的记录。如果不是这样的话,很容易将最终查询更改为从Root表中查找顶级节点。
我已经制作了一个SQLFiddle来显示多个顶级文件夹和一个参差不齐的层次结构的处理。
按请求编辑: 要使用Root作为父文件夹名称的源,您可以在最终查询中执行此操作:
SELECT hr.DocNumber, hr.ParentNumber AS TopFolderNumber, fdd.Name AS DocName, r.Name AS TopFolderName
FROM HierarchyRank hr
LEFT JOIN FolderDocument fdd
ON hr.DocNumber = fdd.DocNumber
LEFT JOIN Root r
ON hr.ParentNumber = r.DocNumber
WHERE RankNum = 1