Получение всех потомков корневого узла - PullRequest
0 голосов
/ 19 марта 2019

У меня есть структура базы данных, например

------------------------------------------
NodeId  |   Parent
-----------------------------------------
1           0
2           0
3           1
4           1
5           2
6           2    
7           3
8           3
9           4
10          4
11          5
12          5
13          6    

Формирование древовидной структуры, например

1
->3
  -->7
  -->8
->4
  -->9
  -->10
2
->5
  -->11
  -->12
->6
  -->13

Теперь пользователь может ввести любой идентификатор узла

для получения

  • все узлы под этим ID узла

union

  • все узлы под корневым узлом id узла

Например:
если пользователь щелкнет по идентификатору узла 1,
Результат должен быть (Это я могу достичь с помощью CTE)

1 0
3 1
4 1
7 3
8 3
9 4
10 4

Но если пользователь нажмет на любую серединуузел типа 4
Результат должен быть

4 1
9 4
10 4

Объединение (все узлы под корнем Родитель узла) Корневой родитель узла 4 = 1, поэтому результат должен быть

1 0 
3 1
4 1 (Should be excluded as comes under first query)
7 3
8 3
9 4 (Should be excluded as comes under first query)
10 4 (Should be excluded as comes under first query) 

Это код, который у меня есть:

declare @Node int;
Set @node=1
with [CTE] As
(
  Select [nodeid], [Parent]
  from [NodeTable]
  where [nodeid]=@nodeid

  union

  Select [
  from [Nodetable] [NT]
    inner join [CTE] on [CTE].[nodeid]=[NT].[Nodeid]
)

Select * from [CTE]

Ответы [ 2 ]

0 голосов
/ 19 марта 2019

Один из способов сделать это - использовать рекурсивный cte, который также будет сохранять корневой узел каждой рекурсии, а затем запрашивать этот cte на основе корня нужного узла.

Сначала создайте и заполните образец таблицы: ( Пожалуйста, сохраните этот шаг в ваших будущих вопросах)

DECLARE @T AS TABLE
(
    NodeId int,
    Parent int
);

INSERT INTO @T (NodeId, Parent) VALUES
(1 , 0),
    (3 , 1),
        (7 , 3),
        (8 , 3),
    (4 , 1),
        (9 , 4),
        (10, 4),

(2 , 0),
    (5 , 2),
        (11, 5),
        (12, 5),
    (6 , 2),
        (13, 6);

рекурсивный cte:

WITH CTE AS
(
    SELECT NodeId, Parent, NodeId As Root
    FROM @T
    WHERE Parent = 0
    UNION ALL
    SELECT t.NodeId, t.Parent, Root
    FROM @T As t
    JOIN CTE 
        ON t.Parent = CTE.NodeId
)

Запрос:

SELECT NodeId, Parent
FROM CTE
WHERE Root = (SELECT Root FROM CTE WHERE NodeId = 4)

Результаты:

NodeId Parent
1       0
3       1
4       1
9       4
10      4
7       3
8       3

Вы можете увидеть живое демо на rextester.

0 голосов
/ 19 марта 2019

Вы можете сначала получить RootId указанного узла с первым CTE, а затем использовать CTE2, чтобы получить все дочерние элементы полученного RootId:

    declare @node int;
Set @node=4;
with [CTE] As
(
  Select [nodeid] NodeId, [Parent] Parent
  from [NodeTable]
  where [nodeid]=@node

  union all

  Select [NT].[nodeid] ni, [NT].[Parent] pi
  from [Nodetable] [NT]
    inner join [CTE] 
    on  [CTE].Parent=[NT].NodeId
), [CTE2] As
(
  Select [nodeid] NodeId, [Parent] Parent
  from [NodeTable]
  where [nodeid]= (select top 1 NodeId from CTE order by NodeId)

  union all

  Select [NT].[nodeid] ni, [NT].[Parent] pi
  from [Nodetable] [NT]
    inner join [CTE2] 
    on [CTE2].NodeId=[NT].Parent
)


Select * from [CTE2]
order by NodeId

Кроме того, если вы хотите исключить сам узел и его дочерние элементы, вы можете добавить CTE3 получение дочерних узлов и использовать их, кроме как для получения желаемого результата:

declare @node int;
Set @node=4;
with [CTE] As
(
  Select [nodeid] NodeId, [Parent] Parent
  from [NodeTable]
  where [nodeid]=@node

  union all

  Select [NT].[nodeid] ni, [NT].[Parent] pi
  from [Nodetable] [NT]
    inner join [CTE] 
    on  [CTE].Parent=[NT].NodeId
), [CTE2] As
(
  Select [nodeid] NodeId, [Parent] Parent
  from [NodeTable]
  where [nodeid]= (select top 1 NodeId from CTE order by NodeId)

  union all

  Select [NT].[nodeid] ni, [NT].[Parent] pi
  from [Nodetable] [NT]
    inner join [CTE2] 
    on [CTE2].NodeId=[NT].Parent
), [CTE3] As
(
  Select [nodeid] NodeId, [Parent] Parent
  from [NodeTable]
  where [nodeid]=@node

  union all

  Select [NT].[nodeid] ni, [NT].[Parent] pi
  from [Nodetable] [NT]
    inner join [CTE3] 
    on  [CTE3].NodeId = [NT].Parent
)

Select * from [CTE2]
except
Select * from [CTE3]
order by NodeId
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...