Подсчитать количество потомков рекурсивно - PullRequest
6 голосов
/ 18 марта 2011

У меня есть таблица с навигацией, которая снова соединяется с помощью ParentId.Я пытаюсь подсчитать, сколько потомков у каждой записи, я знаю, что мне нужно увеличить счетчик в рекурсии, я просто не знаю, как это сделать!

Любая помощь будет принята с благодарностью!

CREATE TABLE [dbo].[Navigation](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [AnchorText] [varchar](50) NOT NULL,
    [ParentID] [int] NULL)

insert into Navigation
select 'Level 1', null
union
select 'Level 2', 1
union
select 'Level 3', 2
union
select 'Level 4', 3


WITH NavigationCTE (Id, AnchorText, ParentId, NumberofDescendants) as
(
      Select Id, AnchorText, ParentId, 'Number of Descendants Here' as NumberofDescendants
      from dbo.Navigation nav

      union ALL 

      select nav.Id, nav.AnchorText, nav.ParentId,  'Number of Descendants Here' as NumberofDescendants
      from dbo.Navigation nav

      join Navigation ON nav.ParentId = nav.Id
)


SELECT * FROM NavigationCTE

РЕДАКТИРОВАТЬ Добавлен уровень и увеличение в рекурсии:

WITH NavigationCTE (Id, AnchorText, ParentId, Level) as
(
      Select nav.Id, nav.AnchorText, nav.ParentId, 0 as Level
      from dbo.Navigation AS nav

      UNION ALL 

      select nav.Id, nav.AnchorText, nav.ParentId, Level + 1
      from dbo.Navigation AS nav

      join Navigation AS nav2 ON nav.ParentId = nav2.Id
)


SELECT * FROM NavigationCTE

1 Ответ

4 голосов
/ 18 марта 2011

Common Table Expressions предоставляют рекурсивную функциональность , которая вам нужна. Изучите создание и использование поля Level в примере запроса статьи. Он выполняет именно то приращение, которое вы хотите достичь, начиная с 0 в запросе привязки.

Рабочий запрос на основе предоставленного образца:

WITH NavigationCTE  AS
(   
    SELECT navA.[Id], navA.ParentId, 0 AS depth_lvl
    FROM Navigation as navA

    UNION ALL

    SELECT navB.Id, navB.ParentId, depth_lvl + 1
    FROM Navigation AS navB
    JOIN NavigationCTE AS nav_cte_a
        --ON navB.ParentId = nav_cte_a.Id
        ON nav_cte_a.ParentId = navB.Id
)
SELECT Id, ParentId, coalesce(max(depth_lvl),0)
FROM NavigationCTE
GROUP BY Id, ParentId
ORDER BY Id, ParentId
...