2010-05-12 2 views
3

Похоже, что это было задано и ответило во всех простых случаях, за исключением того, с которым я столкнулся. Я попытался использовать рекурсивный CTE для создания этого; возможно, курсор был бы лучше? Или, может быть, набор рекурсивных функций сделает трюк?иерархические данные из таблицы самореференций в виде дерева

Можно ли это сделать в cte?

рассмотрит следующую таблицу

PrimaryKey ParentKey 
1   NULL  
2   1  
3   6 
4   7 
5   2 
6   1 
7   NULL 

должен давать

PK 
1 
-2 
--5 
-6 
--3 
7 
-4 

, где число - знаки равна глубине, моя основная трудность заключается в заказе.

ответ

7

Это своего рода kludgey делать с схемой списка смежности, но это может быть сделано с помощью рекурсивных CTE:

WITH Hierarchy AS 
(
    SELECT 
     PrimaryKey, ParentKey, 
     CAST('/' + CAST(PrimaryKey AS varchar(10)) AS varchar(50)) AS [Path], 
     CAST('' AS varchar(50)) AS Prefix 
    FROM @Tbl 
    WHERE ParentKey IS NULL 

    UNION ALL 

    SELECT 
     t.PrimaryKey, t.ParentKey, 
     CAST(h.[Path] + '/' + CAST(t.PrimaryKey AS varchar(10)) AS varchar(50)), 
     CAST(h.Prefix + '-' AS varchar(50)) 
    FROM Hierarchy h 
    INNER JOIN @Tbl t 
     ON t.ParentKey = h.PrimaryKey 
) 
SELECT [Path], Prefix + CAST(PrimaryKey AS varchar(10)) AS Node 
FROM Hierarchy 
ORDER BY [Path] 

Чтобы получить точные результаты, которые вы хотите, вам нужно как Prefix столбца (что делает «отступы») и суррогатная колонка Path, что фактически делает заказ.

+0

Хорошая работа. Спасибо за решение. –

1

Вот мое предложение - вы также получаете путь к каждому узлу, если хотите. Измените вызов str (x, 4) - введите 4 максимальную длину первичного ключа при преобразовании в десятичную.

WITH TreePrinter(id, parent, path, prefix) AS 
(
    SELECT 
     PrimaryKey, ParentKey, 
     CAST(str(PrimaryKey,4) AS varchar(max)), 
     CAST('' AS varchar(max)) 
    FROM YourTable 
    WHERE ParentKey IS NULL 
    UNION ALL 
    SELECT child.PrimaryKey, child.ParentKey, 
    CAST(parent.path+'/'+STR(child.PrimaryKey,4) AS varchar(max)), 
    CAST(parent.prefix+'-' AS varchar(max)), 
    FROM YourTable parent 
    INNER JOIN TreePrinter child ON child.id=parent.ParentKey 
) 
SELECT prefix+str(id) FROM TreePrinter 
ORDER BY path 
Смежные вопросы