Подсказки не разрешены для ссылок на рекурсивные выражения общей таблицы (CTE). Рассмотрите возможность удаления подсказки из рекурсивной ссылки CTE ‘CTE’

#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. Это имело бы больше смысла в качестве комментария к предыдущему ответу, поскольку вы действительно предлагаете дополнительную модификацию этого ответа.