I'm trying to generate a path from the name of an item's parents. For example if test has for parent dad the path would be dad/test; and if dad had for parent gran the path of test would be gran/dad/test.
I only have the id of the child, so far I only have a query which generates the paths of everyone recursively and then selects the right one but that doesn't really seem efficient.
WITH SubItems
AS (
SELECT CAST([Name] AS VARCHAR(255)) AS [Path],
Id,
ParentId,
0 AS Depth
FROM Items
WHERE Id = 1 -- First parent of everyone
UNION ALL
SELECT CAST(CONCAT(parent.[Path], '/', sub.[Name]) AS VARCHAR(255)),
sub.Id,
sub.ParentId,
parent.Depth + 1
FROM Items sub
JOIN SubItems parent ON parent.Id = sub.ParentId
)
SELECT [Path]
FROM SubItems
WHERE Id = 1425 -- SubItem I want the path of
I can also go upwards, which would be faster but I can't create the path this way. I could try to concatenate all the results ordered by the "depth" but again this doesn't seem right.
DECLARE @Path;
WITH ParentItems
AS (
SELECT [Name],
Id,
ParentId,
0 AS Depth
FROM Items
WHERE Id = 1425 -- SubItem I want the path of
UNION ALL
SELECT [Name],
parent.Id,
parent.ParentId,
sub.Depth - 1
FROM Items parent
JOIN ParentItems sub ON sub.ParentId = parent.Id
)
SELECT @Path = COALESCE(@Path + '/', '') + [Name]
FROM ParentItems
ORDER BY Depth;
SELECT @Path;
Is there a way to go upwards recursively?
Something like this for example, where ParentPath
would be equal to CONCAT(ParentPath, '/', [Path])
again:
WITH ...
SELECT CONCAT(ParentPath, '/', [Name])
FROM Items
I know in C# you could do something like:
function getPath() {
return (parent?.getPath() ?? "") + "/" + this.Name;
}
Edit: Why I can't construct the path going up, like this:
WITH ParentItems AS (
SELECT i.Name, i.Id, i.ParentId, 0 AS Depth,
CONVERT(VARCHAR(MAX), i.Name) as path
FROM Items i
WHERE i.Id = 1425 -- SubItem I want the path of
UNION ALL
SELECT i.Name, i.Id, i.ParentId, pi.Depth - 1,
CONCAT(pi.Name, '/', i.[Path])
FROM Items i JOIN
ParentItems pi
ON pi.ParentId = parent.Id
)
SELECT *
FROM ParentItems
ORDER BY Depth;
Assuming the example from above where gran is parent to dad is parent to test, the result of this query would be:
| name | path |
|------|---------------|
| gran | gran/dad/test |
| dad | dad/test |
| test | test |
While it should be the opposite:
| name | path |
|------|---------------|
| gran | gran/ |
| dad | gran/dad |
| test | gran/dad/test |
This is because of the way the query passes the name of the child upwards, adding it to the path of its parent rather than the opposite.