Почему мы не можем использовать внешние соединения в Recursive CTE? - PullRequest
11 голосов
/ 03 февраля 2012

Рассмотрим ниже

;WITH GetParentOfChild AS
    (
        SELECT 
            Rn = ROW_NUMBER() Over(Order By (Select 1))
            ,row_id AS Parents
            ,parent_account_id  As ParentId 
        FROM siebelextract..account
        WHERE row_id = @ChildId
        UNION ALL
        SELECT 
            Rn + 1
            ,a.row_id as Parents
            ,a.parent_account_id As ParentId    
        FROM siebelextract..account a
        JOIN GetParentOfChild gp on a.row_id = gp.ParentId
    )

SELECT TOP 1 @ChildId = Parents 
FROM GetParentOfChild
ORDER BY Rn DESC

Что он делает, так это то, что для любого потомка он вернет родительского уровня корневого уровня .... Программа все время прекрасно работает ...

Просто из любопытства / эксперимента я изменил JOIN на Left Outer Join, и он сообщил

Сообщение 462, уровень 16, состояние 1, процедура GetParent, строка 9 Внешнее объединение не допускается в рекурсивной части рекурсивного общего табличного выражения 'GetParentOfChild'.

Мой вопрос: почему рекурсивная часть CTE не может принять левое внешнее соединение? Это по замыслу?

Спасибо

Ответы [ 2 ]

10 голосов
/ 14 марта 2015

Вы не можете использовать LEFT JOIN с рекурсивным CTE, но вы можете использовать OUTER APPLY, который должен давать те же результаты.

7 голосов
/ 03 февраля 2012

Да, это специально, прочитайте Рекомендации по определению и использованию рекурсивных выражений общих таблиц

Следующие элементы не разрешены в определении CTE_query_ рекурсивный член:

  • ВЫБЕРИТЕ DISTINCT
  • GROUP BY
  • HAVING
  • Скалярная агрегация
  • TOP
  • ВЛЕВО, ВПРАВО, НАРУЖНОЕ СОЕДИНЕНИЕ (ВНУТРЕННЕЕ СОЕДИНЕНИЕ разрешено)
  • подзапросы

Обратите внимание, что если ваш запрос сделать левое присоединение к нему сам с помощью CTE, он может превратиться в бесконечную рекурсию.

...