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

时间:2012-02-03 09:53:37

标签: 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

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

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

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

我的问题是为什么CTE的递归部分不能接受左外连接?这是设计吗?

由于

3 个答案:

答案 0 :(得分:10)

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

答案 1 :(得分:7)

是的,这是设计,请阅读Guidelines for Defining and Using Recursive Common Table Expressions

  

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

     
      
  • SELECT DISTINCT
  •   
  • GROUP BY
  •   
  • HAVING
  •   
  • 标量聚合
  •   
  • TOP
  •   
  • LEFT,RIGHT,OUTER JOIN(允许内部联接)
  •   
  • 子查询
  •   

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

答案 2 :(得分:0)

另一种选择是使用DE LEFT OUTER JOINS定义基础CTE,然后将其用作递归CTE中的表:

WITH 
InitialQuery as (
    -- here de left outer joins


),

GetParentOfChild AS
(
        FROM InitialQuery 
)

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