为什么我们不能在递归CTE中使用外连接?

use*_*901 11 sql-server-2005 common-table-expression

考虑以下

;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
Run Code Online (Sandbox Code Playgroud)

它的作用是,给定任何一个孩子,它将返回根级父... ....程序完全正常工作...

出于好奇/实验的缘故,我将JOIN更改为Left Outer Join并报告

消息462,级别16,状态1,过程GetParent,第9行在递归公用表表达式'GetParentOfChild'的递归部分中不允许外连接.

我的问题是为什么CTE的递归部分不能接受Left Outer Join?它是按设计的吗?

谢谢

小智 10

你不能使用LEFT JOIN和递归CTE,但你可以使用OUTER APPLY,它应该给出相同的结果.

  • 这是天才。 (2认同)
  • @Michael `tb1.Prop = tb2.Prop 上的 LEFT OUTER JOIN 表 tb2 变为 `OUTER APPLY (select * from table tb2 where tb1.Prop = tb2.Prop) tb2` (2认同)

dan*_*era 7

是的,它是按设计,阅读定义和使用递归公用表表达式的指南

递归成员的CTE_query_definition中不允许以下项:

  • 选择DISTINCT
  • 通过...分组
  • HAVING
  • 标量聚合
  • 最佳
  • LEFT,RIGHT,OUTER JOIN(允许内部联接)
  • 子查询

请注意,如果您的查询通过CTE进行左连接,则自身可以变为无限递归.

  • 我不认为这个答案或链接实际上回答"为什么".我想合并两个左连接(到外部表)来控制下一次迭代的方向,例如.无限递归似乎不是放弃所有while循环的好理由. (12认同)
  • @crokusek,在先前的cte expresion中准备你的coalesce查询,并将它连接到你的递归cte查询中. (3认同)