2017-02-10 7 views
3

У меня есть таблица, в которой хранится бинарное дерево следующим образом:Получить влево или вправо на основе на ancenstor для бинарного дерева

Id ParentId Level Placement 
47 -1  0  0 
23 47  1  0 
86 47  1  1 
5 23  2  0 
29 23  2  1 
68 86  2  0 
8 5  3  1 
31 29  3  1 
67 68  3  0 
. 
. 
. 

Использование MSSQL мне нужно SQL, что данный ParentID и childId, он говорит в refrence к parentId, будь то слева или справа. Например

FindPoistion (ParentId: 47, childId: 34) возвращается влево

FindPoistion (ParentId: 23, childId: 8) возвращается влево

FindPoistion (ParentId: 29, childId: 30) возвращается право

FindPoistion (ParentId: 47, childId: 5) возвращается влево

FindPoistion (ParentId: 47, childId: 62) возвращает право FindPoistion (ParentId: 47, childId: 86) возвращает право

Как написать sql, который дает мне позицию на основе ancenstor?

Над размещением 0 слева и 1 является правильным

enter image description here

это то, что я до сих пор

WITH name_tree 
    AS (SELECT Id, 
       Parentid, 
       Placement    
     FROM BinaryTree 
     WHERE Parentid = 47 and Id= 31 
     -- this is the starting point you want in your recursion 
     UNION ALL 
     SELECT c.Id, 
       c.Parentid, 
       c.Placement 

     FROM BinaryTree c 
       JOIN name_tree p 
        ON p.Id = c.ParentId -- this is the recursion 
        AND c.Id <> c.Parentid 

        ) 
SELECT distinct Id, parentId, Placement 

FROM name_tree 
+1

Кажется довольно легко. Вы должны попробовать что-то и показать нам, что вы пробовали. – manderson

+1

Это похоже на довольно типичный рекурсивный cte. Я бы предположил, что вы используете NULL в качестве ParentID, когда нет ни одного, а не -1. Не только с логической точки зрения, но и с вашим кодом будет немного легче работать. –

+0

Может быть, я в замешательстве ... Если у его стола есть ParentID и Id (Предполагая, что это Child) ... и есть Placement для показа слева или справа ... Почему даже использовать CTE? Это будет просто прямой оператор select с parentid/id в качестве параметров, так как он сказал, что ему нужно только знать, находится ли он слева или справа. Поправьте меня, если я ошибаюсь в своих мыслях. – manderson

ответ

2
Declare @YourTable table (id int,ParentId int) 
Insert into @YourTable values (47,-1),(23,47),(86,47),(5,23),(29,23),(68,86),(8, 5),(31,29),(67,68),(62,67),(30,31),(34,31),(42,34),(40,42) 

Declare @Top int   = 47 
Declare @Fetch int   = 31 

;with cteP as (
     Select ID 
      ,ParentId 
      ,Level=1 
     From @YourTable 
     Where [email protected] 
     Union All 
     Select r.ID 
      ,r.ParentId 
      ,p.Level+1 
     From @YourTable r 
     Join cteP p on r.ParentId = p.ID) 
Select ID = @Top 
     ,ParentID = -1 
     ,Level = 0 
     ,Placement = 0 
Union All 
Select A.ID 
     ,ParentID = case when A.Level=1 then @Top else A.ParentId end 
     ,A.Level 
     ,Placement = case when A.Level=1 then IIF(A.ID<@Top,0,1) 
        else case when IsNull(B.ID,A.ParentId) < A.ID then 1 else 0 
        end end 
From cteP A 
Left Join cteP B on (A.ParentId=B.ParentId and B.ID<> A.ID) 

Возвращает

enter image description here

Хотя следующие Возвращения

Declare @Top int   = 47 
Declare @Fetch int   = 31 

enter image description here

+0

Молодец, сэр !!! Я, как обычно, завалялся на работе, и у меня не было шанса вернуться сюда. Тем временем вы выложили полностью рабочее решение, которое прибивает его так, как я его понимаю. –

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