2016-03-12 3 views
0

У меня есть следующие таблицы в SQL Server:Рекурсивный CTE в SQL Server последний узел

| id | Name | ParentId |  
| 1 | world | Null  | 
| 2 | Region | 1  | 
| 3 | Country | 2  | 
| 4 | State | 3  | 
| 5 | City | 4  | 
| 6 | Street | 5  | 

Число иерархий не зафиксировано.

Мне нужен выход в виде улицы, города, штата, страны, региона, мира.

Запуск следующий код SQL:

WITH Hierarchy (ChildId, ChildName, ParentId, Childs) AS 
(
    SELECT 
     Id, Name, ParentId, CAST('' AS VARCHAR(MAX)) 
    FROM 
     UserType AS LastGeneration 
    WHERE 
     Id NOT IN (SELECT COALESCE(ParentId, 0) FROM UserType) 

    UNION ALL 

    SELECT 
     PrevGeneration.Id, PrevGeneration.Name, PrevGeneration.ParentId, 
     CAST(CASE WHEN Child.Childs = '' 
        THEN(CAST(Child.ChildName AS VARCHAR(MAX))) 
        ELSE(Child.Childs + ', ' + CAST(Child.ChildName AS VARCHAR(MAX))) 
     END AS VARCHAR(MAX)) 
    FROM 
     UserType AS PrevGeneration 
    INNER JOIN 
     Hierarchy AS Child ON PrevGeneration.Id = Child.ParentId 
) 
SELECT * 
FROM Hierarchy 
OPTION(MAXRECURSION 32767) 

Это возвращает выход:

Street, City, State, Country, Region 

Что мне нужно, чтобы добавить к рекурсии, чтобы получить последний узел?

Заранее благодарен!

+0

Пройдя от листьев до корня, вы получите много дубликатов (из-за того, что у одного родителя может быть много детей) - лучше использовать подход сверху вниз (1-й бит в ответе Эд). В вашем коде, я думаю, вам нужно выполнить 'PrevGeneration.Name' вместо' Child.ChildName'. При объединении дочернего имени вы не оставляете никаких шансов на уровень корня, поскольку он не является дочерним для какой-либо строки. –

ответ

0

Два разных решения - один работает сверху вниз, другой снизу вверх. Решение сверху вниз немного более эффективно. Я не уверен, какой результат вы хотите для промежуточных строк, поэтому я отправляю оба.

DECLARE @usertype TABLE 
(id int, Name varchar(20),ParentId int) 

INSERT @usertype 
VALUES (1 ,'world',Null),(2 ,'Region',1),(3 ,'Country',2), 
(4 ,'State',3), (5 ,'City',4),(6 ,'Street',5); 


-- Top down 
WITH recCTE 
AS 
(
    SELECT Id, Name, ParentId, CAST(Name AS VARCHAR(MAX)) AS name_hierarchy 
    FROM @UserType 
    WHERE ParentId IS NULL 

    UNION ALL 

    SELECT u.Id, u.name, u.ParentId, u.name + ', ' + r.name_hierarchy 
    FROM recCTE AS r 
    JOIN @usertype AS u 
    ON u.ParentId = r.Id 
) 
SELECT * FROM recCTE; 

--Bottom up 
WITH recCTE2 
AS 
(
    SELECT Id, Name, ParentId, CAST(Name AS VARCHAR(MAX)) AS name_hierarchy 
    FROM @usertype AS u1 
    WHERE NOT EXISTS (SELECT * FROM @usertype AS u2 WHERE u1.Id = u2.ParentId) 

    UNION ALL 

    SELECT u.Id, u.name, u.ParentId, r.name_hierarchy+ ', ' + u.name 
    FROM recCTE2 AS r 
    JOIN @usertype AS u 
    ON r.ParentId = u.Id 
) 
SELECT * FROM recCTE2; 

Ваш код имеет некоторую дополнительную сложность, которая оказалась излишней, исходя из информации, которую вы опубликовали.

+0

Большое спасибо за помощь! –

Смежные вопросы