Получение всех дочерних элементов корневого узла

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

------------------------------------------
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

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

извлекать

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

союз

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

Например:
если пользователь нажмет на идентификатор узла 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]

Пожалуйста, используйте только соответствующий тег версии. Это 2008-р2 или 2012? Кроме того, пожалуйста, прочитайте первый абзац информация о теге sql и редактировать вашего вопроса соответственно.

Zohar Peled 19.03.2019 08:44
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
0
1
94
2

Ответы 2

Вы можете сначала получить 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

Разве корневой уровень всех узлов не равен 1?

Amir Molaei 19.03.2019 09:46

Да, я пропустил это. Ответ обновлен. Также была добавлена ​​часть исключения.

Amir Molaei 19.03.2019 10:15

Один из способов сделать это — использовать рекурсивное 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.

Зохар, все в порядке, но как мне определить «прямые узлы» и «другие узлы корневого узла», спасибо за помощь.

Vikram Sachdeva 19.03.2019 12:11

Можете ли вы отредактировать свой вопрос, чтобы включить точный набор результатов, который вы хотите получить?

Zohar Peled 19.03.2019 12:24

Другие вопросы по теме

Похожие вопросы

Sqlcmd: ошибка: драйвер Microsoft ODBC 11 для SQL Server: не удалось войти в систему для пользователя «sa»
Как избежать двойной привязки элементов управления при обновлении страницы/рендеринге
Как присоединиться к двум разным таблицам, используя UNION в доступе ms
Несколько таблиц для одного внешнего ключа
1-е данные — officeIn, 2-е данные — OfficeOut.. Пользователь может входить несколько раз в день.. мне нужно, сколько времени в формате чч:мм:сс он остается в офисе
Ожидаемая строка или байтовый объект NLTK Mysql
Подсчет последовательных повторяющихся полей с помощью SQL
Sqlalchemy запрос данных временных рядов, отформатированных как пары (шаг, следующий_шаг) смежных во времени выборок
Можем ли мы передать объект как параметр в массиве sql, чтобы предотвратить внедрение sql в nodejs с помощью модуля promise-mysql
Как я могу создать таблицу распределения с помощью SQL, не перечисляя вручную все значения в запросе?