Как правильно обозначить ветви дерева при поиске по глубине

У меня есть дерево с такой структурой:

     __2__3__4
    /   \__5__6
0__1___7/__8__9
   \\
    \\__10__11__12
     \__  __  __
        13  14  15

Узел 1 имеет четырех детей (2,7,10,13), узлы 2 и 7 имеют по два ребенка (оба имеют общий узел 5 в качестве ребенка). Я пытаюсь создать CTE, который будет предоставлять записи, содержащие родительский узел, узел, расстояние от корня и ветвь (или развилку), в которой он находится.

IF (OBJECT_ID('tempdb..#Discovered') IS NOT NULL)
BEGIN
    DROP TABLE #Discovered
END

CREATE TABLE #Discovered
(
    ID int PRIMARY KEY NOT NULL,
    Predecessor int NULL,
    OrderDiscovered int
);

INSERT INTO #Discovered (ID, Predecessor, OrderDiscovered)
VALUES (@nodeId, NULL, 0);

    --loop through node connections table in a breadth first manner
WHILE @@ROWCOUNT > 0
BEGIN
    INSERT INTO #Discovered (ID, Predecessor, OrderDiscovered)
    SELECT c.node2_id
               ,MIN(c.node1_id)
               ,MIN(d.OrderDiscovered) + 1

    FROM #Discovered d JOIN node_connections c ON d.ID = c.node1_id
    WHERE c.node2_id NOT IN (SELECT ID FROM #Discovered)
    GROUP BY c.node2_id
END;

SELECT * FROM #Discovered;

WITH BacktraceCTE(Id, Predecessor, OrderDiscovered, Path, fork)

 AS 

 (  

     SELECT d.ID, d.Predecessor, d.OrderDiscovered, CAST(d.ID AS varchar(MAX)), 0

     FROM #Discovered d

     WHERE d.Id = @itemId


     UNION ALL             

     -- Recursive member, select all the nodes which have the previous

     SELECT d.ID, d.Predecessor, d.OrderDiscovered,  

         CAST(cte.Path + '->' + CAST(d.ID as varchar(10)) as varchar(MAX)),
         fork + CONVERT ( Integer, ROW_NUMBER() OVER (ORDER BY d.ID)) - 1

     FROM #Discovered d JOIN BacktraceCTE cte ON d.Predecessor = cte.ID

 )          

 SELECT  Predecessor as node1_id, OrderDiscovered as hop, fork, ID as node2_id, Path FROM BacktraceCTE  
 ORDER BY fork, OrderDiscovered;

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

Однако, используя приведенный выше код, я получу результаты, в которых будет сказано, что узлы со 2 по 5 являются узлом 3 вилки 1 и узлы с 7 по 5 также являются узлами 3 вилки 1.

Вот дерево снова с обозначением ветвей, как они должны выглядеть:

     __2__3__4      :0
    /   \__5__6     :1,2
0__1___7/__8__9     :3
   \\
    \\__10__11__12  :4
     \__  __  __
        13  14  15  :5

Как вы можете видеть для развилок 1 и 2, я думаю, что лучшим методом будет считать ветвь дважды, давая ей свой собственный идентификатор, таким образом сохраняя уникальность комбинации hop и fork.

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

EDIT Набор результатов будет выглядеть следующим образом:

Predecessor, ID, Order Discovered, Path, Fork

  • null, 0, 0, 0, 0, 0

  • 0, 1, 1, 0->1, 0

  • 1, 2, 2, 0->1->2, 0

  • 2, 3, 3, 0->1->2->3, 0

  • 3, 4, 4, 0->1->2->3->4, 0

  • 2, 5, 3, 0->1->2->5, 1

  • 5, 6, 4, 0->1->2->5->6, 1

  • 1, 7, 2, 0->1->7, 2

  • 7, 5, 3, 0->1->7->5, 2

  • 5, 6, 4, 0->1->7->5->6, 2

  • 7, 8, 3, 0->1->7->8, 3

  • 8, 9, 4, 0->1->7->8->9, 3

  • 1, 10, 2, 0->1->10, 4

  • 10, 11, 3, 0->1->10->11, 4

  • 11, 12, 4, 0->1->10->11->12, 4

  • 1, 13, 2, 0->1->13, 5

  • 13, 14, 3, 0->1->13->14, 5

  • 14, 15, 4, 0->1->13->14->15, 5

7
задан Kavet Kerek 23 January 2012 в 14:37
поделиться