#sql-server #tsql #common-table-expression #recursive-query
#sql-server #tsql #common-table-expression #рекурсивный запрос
Вопрос:
У меня есть одна таблица Employee, вот структура таблицы
Name varchar
GUID numeric
ParentGUID numeric
вот некоторые примеры данных
NAME GUID ParentGUID
ABC 1 NULL
BCD 2 1
xyz 3 2
PQR 4 2
MRS 5 3
Эта таблица содержит большую иерархию сотрудников и менеджеров.
Мне нужно выбрать всех сотрудников, относящихся к конкретному сотруднику.
Например. Мне нужны все сотрудники, входящие в BCD, поэтому результат должен быть
xyz 3 2
PQR 4 2
вот мой рекурсивный запрос для этого.
;WITH CTE (Name, GUID, ParentGUID)
AS
(
select distinct B.Name , B.GUID, B.ParentGUID
FROM
EMP B with (nolock)
union All
select a.Name , a.GUID, a.ParentGUID
FROM EMP a with (nolock)
inner join CTE C with (nolock) on a.ParentGUID = c.GUID
)
select *
FROM CTE B with (nolock) where B.Name in ('BCD')
Но это выдает мне ошибку.
Msg 4150, Level 16, State 1, Line 1
Hints are not allowed on recursive common table expression (CTE) references. Consider removing hint from recursive CTE reference 'CTE'.
Кто-нибудь, пожалуйста, может помочь мне исправить этот запрос.
Комментарии:
1. Ну, вы могли бы удалить WITH (NOLOCK), как указано в сообщении об ошибке…
2. Спасибо, С.Каррас После удаления С ПОМОЩЬЮ (NOLOCK) я получаю только 1 запись, я не получаю полную иерархию
Ответ №1:
Вы where B.Name in ('BCD')
фильтруете свой результирующий набор только по одной строке. Измените ее на приведенную ниже, и вы должны получить желаемые результаты:
;with cte (Name, GUID, ParentGUID)
as
(
select distinct B.Name
,B.GUID
,B.ParentGUID
from EMP B
where B.Name in ('BCD')
union All
select a.Name
,a.GUID
,a.ParentGUID
from EMP a
inner join CTE C
on a.ParentGUID = c.GUID
)
select *
from CTE
Комментарии:
1. Привет, спасибо, @iamdave за помощь.
Ответ №2:
Полное удаление WITH (NOLOCK)
только устраняет ошибку, для использования WITH (NOLOCK)
в рекурсивном CTE вам просто нужно поместить ее за пределы только предложения WITH
;with cte (Name, GUID, ParentGUID)
as
(
select distinct B.Name
,B.GUID
,B.ParentGUID
from EMP B
where B.Name in ('BCD')
union All
select a.Name
,a.GUID
,a.ParentGUID
from EMP a
inner join CTE C
on a.ParentGUID = c.GUID
)
select *
from cte WITH (NOLOCK);
Комментарии:
1. Это имело бы больше смысла в качестве комментария к предыдущему ответу, поскольку вы действительно предлагаете дополнительную модификацию этого ответа.