У меня есть структура базы данных, например
------------------------------------------
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
Теперь пользователь может ввести любой идентификатор узла
извлекать
союз
Например:
если пользователь нажмет на идентификатор узла 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]


Вы можете сначала получить 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?
Да, я пропустил это. Ответ обновлен. Также была добавлена часть исключения.
Один из способов сделать это — использовать рекурсивное 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.
Зохар, все в порядке, но как мне определить «прямые узлы» и «другие узлы корневого узла», спасибо за помощь.
Можете ли вы отредактировать свой вопрос, чтобы включить точный набор результатов, который вы хотите получить?
Пожалуйста, используйте только соответствующий тег версии. Это 2008-р2 или 2012? Кроме того, пожалуйста, прочитайте первый абзац информация о теге sql и редактировать вашего вопроса соответственно.