2013-11-24 2 views
0

Я хотел бы сгенерировать запрос, который перечисляет родительский узел с каждым из его дочерних узлов и узлами для детей (и т.д. и т. Д.) Ниже друг друга. Точно так же, как вы бы структурировали комментарий с ответом и ответом на это.SQL Server Parent/Child Ordering (Возможная рекурсия?)

Например, учитывая эти данные:

ID ParentID 
-------------- 
1 0 
2 0 
3 2 
4 2 
5 0 
6 1 
7 2 
8 7 

Я хотел бы получить запрос структурированного, как это:

ID ParentID 
-------------- 
1 0 
6 1 
2 0 
3 2 
4 2 
7 2 
8 7 
5 0 

Я знаю, что нужно Рекурсивный CTE я верю, но как?

Благодаря

+0

ли требуется несколько уровней воспитания детей: есть (9, 8) возможность? –

+0

@TI Большое спасибо - вы получили в связи с сообщением. – Cheeky

+0

Совет. Обычно для указания узла верхнего уровня используется «ParentID» из NULL. Это позволяет избежать специальной обработки магических чисел или путаницы установки узла как своего родителя, чтобы указать корень. – HABO

ответ

0

попробовать что-то вроде этого ...

;WITH 
    cte (EmpID, ParentID, EmpLevel) 
    AS 
    (
    SELECT ID, ParentID, 1 
    FROM Table 
    WHERE ParentID = 0 

    UNION ALL 

    SELECT t.ID, t.ParentID,c.EmpLevel + 1 
    FROM Table t 
     INNER JOIN cte c 
     ON t.ParentID = c.EmpID 
) 
SELECT 
    EmpID,EmpLevel 
FROM cte 
ORDER BY EmpID,EmpLevel 
1

Кажется, что вы хотели бы сделать DFS (Depth First Search) на структуре дерева, хранящейся в таблице.

   0 
      /| \ 
      / | \ 
     / | \ 
     / |  \ 
     1  2  5 
     | /| \ 
     6 3 4 7 
        | 
        8 

Логика кода будет:

DFS(Node p){ 
    children = GetChildren(p) 
    foreach (c in children) { 
     Print("ID: " + c + " Parent ID: " + p) 
     DFS(c) 
    } 
} 

Теперь SQL Server. Выбор узлов, которые непосредственно дети данного узла легко:

SELECT [ID] FROM [Table] WHERE [ParentID] = @parentID 

Создайте временную таблицу для хранения результатов:

CREATE TABLE #temp(ID int, ParentID int); 

Тогда либо рекурсивно SELECT INTO таблицы результатов или сделать это в цикле while.

1

SQL2008 +:

DECLARE @MyTable TABLE 
( 
    ID INT PRIMARY KEY, 
    ParentID INT NOT NULL 
); 
INSERT @MyTable (ID, ParentID) 
      SELECT 1, 0 
UNION ALL SELECT 2, 0 
UNION ALL SELECT 3, 2 
UNION ALL SELECT 4, 2 
UNION ALL SELECT 5, 0 
UNION ALL SELECT 6, 1 
UNION ALL SELECT 7, 2 
UNION ALL SELECT 8, 7; 

WITH ConvertAdiacentListToHierarchyID 
AS 
(
SELECT x.ID, x.ParentID, CONVERT(VARCHAR(8000), '/' + CONVERT(VARCHAR(10), x.ID) + '/') AS Node 
FROM @MyTable x 
WHERE x.ParentID = 0 
UNION ALL 
SELECT x.ID, x.ParentID, CONVERT(VARCHAR(8000), y.Node + CONVERT(VARCHAR(10), x.ID) + '/') AS Node 
FROM @MyTable x 
INNER JOIN ConvertAdiacentListToHierarchyID y ON x.ParentID = y.ID 
) 
SELECT cte.*, CONVERT(HIERARCHYID, cte.Node) AS NodeAsHierachyID 
FROM ConvertAdiacentListToHierarchyID cte 
ORDER BY NodeAsHierachyID; 

Результаты:

ID ParentID Node NodeAsHierachyID 
-- -------- ------- ---------------- 
1 0  /1/  0x58 
6 1  /1/6/ 0x5CA0 
2 0  /2/  0x68 
3 2  /2/3/ 0x6BC0 
4 2  /2/4/ 0x6C20 
7 2  /2/7/ 0x6CE0 
8 7  /2/7/8/ 0x6CF440 
5 0  /5/  0x8C 
Смежные вопросы