Выход из рекурсивного общего табличного выражения, если результирующий набор содержит некоторое значение - PullRequest
4 голосов
/ 21 октября 2010

Учитывая следующую таблицу:

create table TreeNode
(
  ID int not null primary key,
  ParentID int null foreign key references TreeNode (ID)
)

Как я могу написать общее табличное выражение для начала в корне (WHERE ParentID IS NULL) и обходить его потомков, пока результирующий набор не содержит некоторый целевой узел (например, Где ID = n)?Легко начать с целевого узла и перейти вверх к корню, но это не сгенерирует тот же набор результатов.В частности, узлы, имеющие того же родителя, что и целевой узел, не будут включены.

Моя первая попытка была:

with Tree as
(
  select
    ID,
    ParentID
  from
    TreeNode
  where
    ParentID is null
  union all select
    a.ID,
    a.ParentID
  from
    TreeNode a
    inner join Tree b
      on b.ID = a.ParentID
  where
    not exists (select * from Tree where ID = @TargetID)
)

, которая выдает ошибку: Recursive member of a common table expression 'Tree' has multiple recursive references.

ПРИМЕЧАНИЕ : меня интересует только обход сверху вниз.

1 Ответ

1 голос
/ 21 октября 2010

ОБНОВЛЕНИЕ 2:

Третья попытка, которая "пересекает" дерево в обоих направлениях.

Создайте CTE из всех ParentIDs от Target доroot.Затем выберите из tree nodes, чьи ID или Parent отображаются в коротком списке.

--
;
WITH    Tree
          AS ( SELECT   ID
                       ,ParentID
               FROM     TreeNode
               WHERE    [ID] = @targetId
               UNION ALL
               SELECT   a.ID
                       ,a.ParentID
               FROM     TreeNode a
                        INNER JOIN Tree b ON b.ParentID = a.ID
             )
    SELECT  *
    FROM    [dbo].[TreeNode] n
    WHERE  EXISTS (SELECT *
                   FROM [Tree] t
                   WHERE [t].[ID] = [n].[ID]
                         OR [t].[ID] = [n].[ParentID]
                  )
...