Home > Blockchain >  Get path from self referencing table
Get path from self referencing table

Time:08-24

I have a SQL Server database with a self referencing table. The depth of the structure can be between 1 and 20

  • ID - primary key
  • Name - nvarchar(256)
  • ParentID - int

Typical data:

Id Name ParentId
1 Folder1 NULL
2 Folder2 1
3 Folder3 2
4 Folder4 3

I want to provide an Id and list all "parent" folders

Id=3 : output: "Folder1\Folder2\Folder3"

Id=4 : output: "Folder1\Folder2\Folder3\Folder4"

I looked at Writing a recursive SQL query on a self-referencing table and wrote the following:

declare @id int
set @id = 4
;with ItemPath as 
    (
        select a.Id, cast(a.Name as nvarchar(max)) as Name, a.ParentId
        from ParentChild a
        where a.Id = @id --Starting point

        union all

        select a.Id, a.Name    '/'   parent.Name, a.ParentId
        from ParentChild as a
        inner join ItemPath as parent on parent.ParentId = a.Id 
    )
select * 
from ItemPath

but this gives me several rows:

Id Name ParentId
4 Folder4 3
3 Folder3/Folder4 2
2 Folder2/Folder3/Folder4 1
1 Folder1/Folder2/Folder3/Folder4 null

I just want the last result

CodePudding user response:

First, you are trying to filter values ​​in the wrong place. This should be done not in the CTE, but in the main query, since the CTE is used to build the tree and generate the Name value.

Second, you have an error in the CTE in the recursive part when joining the CTE. You have on parent.ParentId = a.Id but you need the opposite on a.ParentId = parent.Id.

So you query would be like this

declare @id int;
set @id = 4;

WITH folder_tree AS (
    SELECT 
        id, 
        CAST(name AS nvarchar(max)) AS name, 
        parentid 
    FROM folders 
    WHERE parentid IS NULL
    UNION ALL
    SELECT 
        f.id,
        CAST(ft.name   '/'   f.name AS nvarchar(max)),
        f.parentid 
    FROM folders f
    JOIN folder_tree ft ON f.parentid = ft.id
)
SELECT * FROM folder_tree
WHERE id = @id

Query output

id name parentid
4 Folder1/Folder2/Folder3/Folder4 3

You can check a working demo here

  • Related