Максимальный уровень рекурсии SQL Server - PullRequest
0 голосов
/ 29 января 2012

У меня есть базовая рекурсивная таблица настройки в SQL 2008 со следующей структурой:

CREATE TABLE [dbo].[Employee]
(
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](100) NOT NULL,
[ManagerId] [int] NULL,
CONSTRAINT [PK_Employee] PRIMARY KEY CLUSTERED ([Id] ASC)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

ALTER TABLE [dbo].[Employee]  WITH CHECK ADD  CONSTRAINT [FK_Employee_Employee] FOREIGN KEY([ManagerId]) REFERENCES [dbo].[Employee] ([Id])

Основываясь на паре разных статей в Интернете, я нашел, где можно написать запрос, такой как следующий, для возврата«менеджер» и все дочерние записи, содержащиеся под:

WITH DirectRelationships AS
(
SELECT Id, Name, ManagerId, Depth = 0
FROM Employee
WHERE ManagerId = 1
UNION ALL
SELECT e.Id, e.Name, e.ManagerId, Depth = Depth + 1
FROM Employee e
INNER JOIN DirectRelationships DR ON DR.Id = e.ManagerId
WHERE Depth <= 2 /* this doesn't work */
)
SELECT * FROM DirectRelationships

Когда я запускаю оператор выбора выше без «WHERE Depth <= 2», я получаю четыре столбца назад (Id, Name, ManagerId, Depth)которые показывают точные записи, которые я ищу.Проблема, с которой я сталкиваюсь, состоит в том, что глубина основана на общей глубине из корневой записи (где ManagerId равен нулю), а не на глубине записи от запрошенного менеджера. </p>

Например, предположим, у меня есть следующие данныев этой таблице:

select * from Employee;

Id  | Name             | ManagerId | Depth
------------------------------------------
1    CEO                 0           0
2    National Director   1           1
3    Regional Director   2           2
4    Store Director      3           3
5    Clerk               4           4
6    Clerk #2            4           4

То, что я хочу, чтобы мой запрос был в состоянии сделать, это получить уровень менеджера (скажем, Национальный директор или Id # 2) и указать количество уровней для рекурсивного извлечения (скажем,2).Это вернуло бы следующее:

Id  | Name             | ManagerId | Depth
------------------------------------------
2    National Director   1           0 /*top level requested */
3    Regional Director   2           1 /*new depth based on requested parent */
4    Store Director      3           2 /*new depth based on requested parent */

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

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

1 Ответ

1 голос
/ 29 января 2012

Попробуйте запустить:

WITH DirectRelationships AS
(
    SELECT Id, Name, ManagerId, Depth = 0
    FROM Employee
    WHERE Id = 2

    UNION ALL

    SELECT e.Id, e.Name, e.ManagerId, Depth = Depth + 1
    FROM Employee e
        INNER JOIN DirectRelationships DR ON DR.Id = e.ManagerId
)
SELECT * 
FROM DirectRelationships 
WHERE Depth <= 2

Вы должны получить искомый результат:

Id Name              ManagerId Depth
-- ----------------- --------- -----
2  National Director 1         0
3  Regional Director 2         1
4  Store Director    3         2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...