#sql #sql-server-2008 #tsql #stored-procedures #hierarchy
#sql #sql-server-2008 #tsql #хранимые процедуры #иерархия
Вопрос:
Описание:
Существует таблица, состоящая из двух столбцов (ParentID и childID), которая отображает иерархию некоторых объектов. Каждый идентификатор может быть представлен в столбце ParentID только один раз. Это означает, что у каждой сущности есть только одна дочерняя сущность.
Проблема: мне нужно проверить, есть ли объект (его идентификатор) в списке потомков родительского объекта.
Комментарии:
1. Вы пытаетесь выполнить обнаружение цикла?
2. Существует ли уникальное ограничение на ParentID?
3. Пара ParentID и childID является уникальным ограничением. Но никаких других ограничений в таблице нет.
Ответ №1:
DECLARE @parentId INT
DECLARE @childId INT
DECLARE @targetChildId INT
SET @targetChildId=<put id of a child you want to find>
SET @parentId=<put id of a parent you are looking child for>
SET @childId=0
WHILE (@childId<>@targetChildId)
BEGIN
IF(EXISTS(SELECT ChildId FROM Hierarchies WHERE ParentId=@parentId))
BEGIN
SET @childId=(SELECT ChildId FROM Hierarchies WHERE ParentId=@parentId)
SET @parentId=@childId
END
ELSE
BEGIN
SET @childId=0
BREAK
END
END
PRINT @childId
Возвращает 0, если целевой потомок не найден в целевом родителе.
Ответ №2:
Пример данных:
CREATE TABLE [dbo].[EntityHierarchy]
(
[EntityId] INT,
[ChildEntityId] INT
)
INSERT [dbo].[EntityHierarchy]
VALUES (1, 2),
(2, 3),
(3, 4),
(4, 1) -- Cycle
Найти циклические связи:
DECLARE @SearchEntityId INT = 1
;WITH [cteRursive] AS
(
SELECT 1 AS [ROW_NUMBER],
[ChildEntityId] AS [EntityId]
FROM [dbo].[EntityHierarchy]
WHERE [EntityId] = @SearchEntityId
UNION ALL
SELECT r.[ROW_NUMBER] 1,
h.[ChildEntityId]
FROM [cteRursive] r
INNER JOIN [dbo].[EntityHierarchy] h
ON r.[EntityId] = h.[EntityId]
WHERE h.[ChildEntityId] <> @SearchEntityId
)
SELECT h.*
FROM [cteRursive] r
INNER JOIN [dbo].[EntityHierarchy] h
ON r.[EntityId] = h.[EntityId]
WHERE r.[ROW_NUMBER] = (SELECT MAX([ROW_NUMBER]) FROM [cteRursive])
Я использую рекурсивный CTE для составления списка потомков. Потомок последнего потомка либо создает цикл, либо нет.
Комментарии:
1. Хорошее указание, но мне просто нужно проверить, есть ли childID в списке потомков ParentID. Без какого-либо цикла.
2. Я немного обновил этот CTE, и он работает нормально. Именно то, что я искал.