Самый эффективный способ запроса таблицы с детьми, внуками и т. Д. - PullRequest
0 голосов
/ 09 января 2020

У меня есть таблица со списком работ, в которых есть дети, внуки и т. Д. c. Там нет предела на уровне иерархии, он понижается. Таблица имеет идентификатор, имя и идентификатор родителя. Так, например, таблица Job может выглядеть следующим образом:

ID  Name               Parent ID
1   Education          null
2   IT                 null
3   Teacher            1
4   MS Teacher         3
5   7th Grade          4
6   Sys Admin          2
7   HS Teacher         3
8   12th Grade         7
9   IT Support         6
10  Developer          2

Существует также таблица UserToJob, которая является просто JobID и UserID. Человек может быть указан в более чем одной вакансии.

Я ищу наиболее эффективный способ получить всех людей с указанной работой и всех потомков, поэтому, если я хочу запросить об образовании, то он возвращает Образование, Учитель, Учитель MS, 7-й класс, Учитель HS и 12-й класс.

Прямо сейчас моя лучшая попытка выглядит следующим образом:

with 
Closure AS (
select j.ID as AncestorID, j.ID as DescendantID, 0 as Depth from Jobs j
UNION ALL
select CTE.AncestorID, j.ID, CTE.Depth + 1 from Jobs j
inner join Closure CTE on j.ParentID = CTE.DescendantID
),
Job AS ( select j.UserID as ID from UserToJob j
where j.JobID in (select DescendantID from Closure where AncestorID in (1))
)

Я хочу, чтобы она могла выполнять запросы более чем на одну работу одновременно, например, если бы я хотел, чтобы все администраторы Education и Sys Я бы изменил AncestorID in (1) на AncestorID in (1, 6) в последней строке моей попытки.

1 Ответ

0 голосов
/ 09 января 2020

У вас есть пункт where в неправильном месте. Вы хотите ограничить root вашего рекурсивного cte, чтобы возвращать только те строки первого уровня, которые вас интересуют.

Это должно указать вам правильное направление.

declare @Jobs table
(
    ID int
    , Name varchar(50)
    , ParentID int
)
insert @Jobs values
(1, 'Education', null)
, (2, 'IT', null)
, (3, 'Teacher', 1)
, (4, 'MS Teacher', 3)
, (5, '7th Grade', 4)
, (6, 'Sys Admin', 2)
, (7, 'HS Teacher', 3)
, (8, '12th Grade', 7)
, (9, 'IT Support', 6)
, (10, 'Developer', 2)

select *
from @Jobs;

with Closure AS 
(
    select j.ID as AncestorID
        , j.ID as DescendantID
        , 0 as Depth 
    from @Jobs j
    where j.ID in (1, 6)

    UNION ALL

    select CTE.AncestorID
        , j.ID
        , CTE.Depth + 1 
    from @Jobs j
    inner join Closure CTE on j.ParentID = CTE.DescendantID
)

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