none
看不懂公共表达式(CTE)是如何完成递归的,求大牛解释 RRS feed

  • 问题

  • 看到了一个CTE递归的实际应用,这个表本身是很简单.

    CET递归如下所写

    with
    district as 
    (
        --  获得第一个结果集,并更新最终结果集
        select * from t_tree where node_name= N'辽宁省'
        union all
        --  下面的select语句首先会根据从上一个查询结果集中获得的id值来查询parent_id         
        --  字段的值,然后district就会变当前的查询结果集,并继续执行下面的select 语句
        --  如果结果集不为null,则与最终的查询结果合并,同时用合并的结果更新最终的查
        --  询结果;否则停止执行。最后district的结果集就是最终结果集。
        select a.* from t_tree a, district b
                   where a.parent_id = b.id
    )
    select * from district
    


    它的解释我看的云里雾里,就是没看懂,递归跳出的条件是什么。按照其它地方的解释:递归跳出的条件是定位点,也就是第一条语句
    select * from t_tree where node_name= N'辽宁省'
    可问题就是如果在t_tree表里搜索node_name= N'辽宁省'的话,无论递归到第几级都不可能出现空结果(t_tree表里第一行永远是搜索结果,不可能为空),递归就永远不会跳出了,所以我怎么也无法理解CTE递归是如何跳出的,msdn上关于公共表达式递归的文章我也看过了,还是无法理解,到底CTE递归的“跳出条件”是什么,有人能解释一下这个吗,感觉这个太难理解了

    2011年9月17日 12:17

答案

  • 对于递归的CTE,以你的这个例子来说,

    第一句sql: 这个select * from t_tree where node_name= N'辽宁省'称为定位成员,SQL Server通过此语句来判断是否继续进行递归。

    第二句sql:select a.* from t_tree a, district b  where a.parent_id = b.id 称之为递归成员,其特征为from子句中引用了CTE对象自身。

    递归的终止依赖于定位点成员的,如果理解了这一点,也就理解了递归查询的执行方式。

    cte递归的时候实际上你可以看做将整个表的记录,逐条的放入语句中执行(不在定位成员中的记录进入递归部分执行),只有满足条件的语句才会打印出来。

    回答你的问题:根据上面黑体部分,表的记录循环结束,也就跳出递归了。

    可以通过查询计划来看到更多的信息,或者参考MSDN相关文章。


    family as water
    2011年9月17日 16:33