且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

SQL Server使用递归CTE获取路径

更新时间:2023-02-05 23:28:59

这是一个可行的解决方案.用语言很难描述它为什么起作用,因此我建议拆开查询以了解它如何起作用.基本上,我们使用 ROW_NUMBER 来递归地构建要查看的路径字符串,以跟踪每个新添加的路径属于哪个特定父级.

Here is a working solution. It is difficult to describe in words why this works, so I recommend taking apart the query to see how it works yourself. Basically, we recursively build the path string you want to see, using ROW_NUMBER to keep track to which particular parent each new path addition belongs.

recursiveCte (parentId, id, name, Level, Path, FullPath) AS (
    SELECT d.parentId, d.id, d.name, 0 AS Level,
        CAST(ROW_NUMBER() OVER (ORDER BY d.id) AS nvarchar(max)),
        RIGHT('000' + CAST(ROW_NUMBER() OVER (ORDER BY d.id) AS nvarchar(max)), 3)
    FROM Department AS d
    WHERE parentId = 0 

    UNION ALL

    SELECT d.parentId, d.id, d.name, r.Level + 1,
        r.Path + '.' +
        CAST(ROW_NUMBER() OVER (PARTITION BY r.Level ORDER BY d.id) AS nvarchar(max)),
        r.FullPath + '.' + RIGHT('000' + CAST(ROW_NUMBER() OVER
            (PARTITION BY r.Level ORDER BY d.id) AS nvarchar(max)), 3)
    FROM Department AS d
    INNER JOIN recursiveCte AS r
        ON d.parentId = r.id
)

SELECT parentId, id, name, Level, Path, FullPath
FROM recursiveCte
ORDER BY FullPath;

演示

我稍微修改了原始答案,以便现在使用固定宽度的版本对路径字符串进行排序,即每个数字的固定宽度均为3位数字.这意味着 001 总是会排在 010 之前,这是我们想要的行为.

I slightly edited my original answer so that it now sorts the path string using a fixed-width version, i.e. every number has a fixed width of 3 digits. This means that 001 will always sort before 010, which is the behavior we want.