Я пытаюсь сгенерировать путь из имени родителей элемента. Например, если test имеет для родителя dad , путь будет dad / test ;и если бы папа имел для родителя гран путь test был бы gran / dad / test .
IУ меня есть только идентификатор ребенка, пока у меня есть только запрос, который рекурсивно генерирует пути для всех, а затем выбирает правильный, но это не кажется эффективным.
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
Я также могу пойтивверх, что было бы быстрее, но я не могу создать путь таким образом. Я мог бы попытаться объединить все результаты, упорядоченные по «глубине», но опять-таки это кажется неправильным.
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;
Есть ли способ рекурсивно идти вверх? Что-то вроде этогонапример, где ParentPath
снова будет равно CONCAT(ParentPath, '/', [Path])
:
WITH ...
SELECT CONCAT(ParentPath, '/', [Name])
FROM Items
Я знаю, в C # вы можете сделать что-то вроде:
function getPath() {
return (parent?.getPath() ?? "") + "/" + this.Name;
}
Редактировать: Почему я не могу построить путь, идущий вверх, например:
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;
Принимая пример сверху, где gran является родительским для папа является родительским для test , результат этого запроса будет:
| name | path |
|------|---------------|
| gran | gran/dad/test |
| dad | dad/test |
| test | test |
Хотя должно быть наоборот:
| name | path |
|------|---------------|
| gran | gran/ |
| dad | gran/dad |
| test | gran/dad/test |
Это из-заспособ, которым запрос передает имя потомка вверх, добавляя его к пути его родителя, а не наоборот.