Рекурсивный запрос, который возвращает себя и всех его потомков - PullRequest
3 голосов
/ 17 сентября 2010

Моя таблица 'Уровни' в базе данных SQL Server 2005 выглядит следующим образом:

LevelId Description      ParentLevelId
0       Level_1          NULL
1       Level_2          0
2       Level_3          0
3       Level_4          1
4       Level_5          3

Теперь я хочу создать запрос, который будет производить набор результатов, в котором каждый уровень и все его дочерние элементы,внуки и т. д. возвращаются.Итак, в основном я хочу вернуть вывод, подобный этому:

LevelId Description DescendantId Descendant_Description
0       Level_1     0            Level_1
0       Level_1     1            Level_2
0       Level_1     2            Level_3    
0       Level_1     3            Level_4   
0       Level_1     4            Level_5    
1       Level_2     1            Level_2
1       Level_2     3            Level_3
1       Level_2     4            Level_5
2       Level_3     2            Level_3
3       Level_4     3            Level_4
4       Level_5     4            Level_5 

Как ни странно, я написал аналогичный запрос сегодня, где показаны все уровни и все его предки.Почему-то я застрял, написав похожий запрос для чего-то, что «наоборот».У кого-нибудь есть идеи?

Ответы [ 2 ]

2 голосов
/ 17 сентября 2010
WITH    q (LevelId, Description, DescendantId, Descendant_Description) AS
        (
        SELECT  LevelId, Description, LevelId, Description
        FROM    mytable
        UNION ALL
        SELECT  t.LevelId, t.Description, q.DescendantId, q.Descendant_Description
        FROM    q
        JOIN    mytable t
        ON      t.ParentLevelId = q.LevelId
        )
SELECT  *
FROM    q
ORDER BY
        LevelId, DescendantId

Поскольку этот запрос возвращает все пары «предок-потомок» в системе (строит так называемое транзитивное замыкание ), все, что вам нужно, чтобы поставить его наоборот, это поменять местами поля и изменить порядок:

WITH    q (LevelId, Description, DescendantId, Descendant_Description) AS
        (
        SELECT  LevelId, Description, LevelId, Description
        FROM    mytable
        UNION ALL
        SELECT  t.LevelId, t.Description, q.DescendantId, q.Descendant_Description
        FROM    q
        JOIN    mytable t
        ON      t.ParentLevelId = q.LevelId
        )
SELECT  DescendantId AS LevelId, Descendant_Description AS Description,
        LevelId AS DescendantId, Description AS Descendant_Description
FROM    q
ORDER BY
        LevelId, DescendantId
0 голосов
/ 17 сентября 2010

Самый простой способ - написать рекурсивный CTE.Прочитайте эту статью для получения более подробной информации: Общие выражения таблиц

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...