06. 父子节点(树)遍历写法小结

原文:06. 父子节点(树)遍历写法小结

对于树/图的遍历,通常有2种算法来实现:迭代(Iteration)和递归(Recursion),迭代是利用循环反复取值/赋值的过程;递归则是反复自己调用自己来获得最终结果。
SQL Server里的递归有32层嵌套限制,目的在于防止代码进入死循环,除非使用提示OPTION (MAXRECURSION 0)。

测试数据:

if OBJECT_ID(‘city‘) is not null
    drop table city
GO
create table city
(
id    int,
name  nvarchar(10),
pid   int,
depth int
)
GO
insert into city
select  1,N‘江苏省‘,0,0 union all
select  2,N‘南京市‘,1,1 union all
select  3,N‘玄武区‘,2,2 union all
select  4,N‘鼓楼区‘,2,2 union all
select  5,N‘浙江省‘,0,0 union all
select  6,N‘杭州市‘,5,1 union all
select  7,N‘西湖区‘,6,2 union all
select  8,N‘滨江区‘,6,2 union all
select  9,N‘苏州市‘,1,1 union all
select 10,N‘吴中区‘,9,2 union all
select 11,N‘吴江区‘,9,2

一. 查找子节点
查找节点1的所有子节点,返回结果如下:

id name pid depth
1 江苏省 0 0
2 南京市 1 1
3 玄武区 2 2
4 鼓楼区 2 2
9 苏州市 1 1
10 吴中区 9 2
11 吴江区 9 2

1. 迭代
(1) 不借助depth,通过not in来向下查找

if OBJECT_ID(‘f_get_child‘) is not null
    drop function f_get_child
GO
create function f_get_child
(
@id int
)
returns @t table(id int)
as
begin
    insert into @t select @id
    --insert into @t select id from city where pid = @id
    while @@ROWCOUNT>0
    begin
        insert into @t
        select a.id
        from city a inner join @t b on a.pid = b.id
        where a.id not in(select id from @t)
    end
    return
end
GO
select * from city where id in(select id from f_get_child(1))

(2) 通过depth来逐层查找

if OBJECT_ID(‘f_get_child‘) is not null
    drop function f_get_child
GO
create function f_get_child
(
@id int
)
returns @t table(id int, depth int)
begin
    declare @depth int
    set @depth = 0
    insert @t select ID,@depth from city where ID =@ID
    while @@ROWCOUNT>0
    begin
        set @depth = @depth + 1
        insert @t select a.ID,@depth
          from city a, @t b
         where a.pid = b.ID
           and b.depth = @depth - 1
    end
    return
end
GO
select * from city where id in(select id from f_get_child(1))

2. 递归
(1) 自定义函数递归

if OBJECT_ID(‘f_get_child‘) is not null
    drop function f_get_child
GO
create function f_get_child
(
@id int
)
returns @t table(id int)
as
begin
    declare @pid int
    set @pid = null
    insert into @t
    select @id
    union all
    select id from city where pid = @id

    if exists(select 1
        from city a inner join @t b on a.pid = b.id
        where a.id not in(select id from @t))
    begin
        insert into @t
        select a.id
        from city a inner join @t b on a.pid = b.id
        where a.id not in(select id from @t)
        union all
        select * from f_get_child(@pid)
    end
    return
end
GO
select * from city where id in(select * from f_get_child(1))

(2) CTE递归

declare @id int
set @id = 1;
with tmp
as
(
select * from city where id = @id
union all
select a.* from city a
inner join tmp b
on a.pid = b.id
)
select * from tmp order by id

二. 查找父节点
查找节点8的所有父节点,返回结果如下:

id name pid depth
5 浙江省 0 0
6 杭州市 5 1
8 滨江区 6 2

1. 迭代
父节点只有一个,不需要做什么限制,一直往上级查找pid就可以了。

if OBJECT_ID(‘f_get_parent‘) is not null
    drop function f_get_parent
GO
create function f_get_parent
(
@id int
)
returns @t table(id int)
as
begin
    declare @pid int
    insert into @t select @id
    select @pid = pid from city where id = @id
    while @pid<>0
    begin
        insert into @t values(@pid)
        select @pid=pid from city where id=@pid
    end
    return
end
GO
select * from city where id in(select * from f_get_parent(8))

2. 递归
(1) 自定义函数递归

if OBJECT_ID(‘f_get_parent‘) is not null
    drop function f_get_parent
GO
create function f_get_parent(@id int)
returns @t table(id int)
AS
begin
    declare @pid int
    select top 1 @pid = pid
    from city
    where id = @id
    if @pid <> 0
    begin
        insert into @t
        select @id
        union all
        select * from f_get_parent(@pid)
    end
    else
    begin
        insert into @t
        select @id
    end
    return
end
GO
select * from city where id in(select * from f_get_parent(8))

(2) CTE递归

declare @id int
set @id = 8;
with tmp
as
(
select * from city where id = @id
union all
select a.* from city a
inner join tmp b
on a.id = b.pid
)
select * from tmp order by id

06. 父子节点(树)遍历写法小结,布布扣,bubuko.com

时间: 2024-10-13 20:48:56

06. 父子节点(树)遍历写法小结的相关文章

JavaScript之DOM-4 文档结构和遍历(节点树、元素树、文档的遍历)

一.节点树 节点树 概念 - HTML DOM 将 HTML 文档视作树结构 - 文档中的元素.属性.文本.注释等都被看作一个节点 - 这种结构被称为节点树: 上下层节点 - 节点树中的节点彼此拥有层级关系,DOM 使用如下属性遍历整棵节点树: 平行的节点 - 节点树中使用如下方法访问平行的兄弟节点: 二.元素树 元素树 概念 - 元素树是节点树的一个子集,只包含其中的元素节点 上下层元素 - 与节点树一样,元素树上的元素节点也有父子关系,使用如下属性可以获取这些关系: 平行的元素 - 元素树使

递归遍历节点树

<!DOCTYPE HTML> <html> <head> <title>遍历节点树</title> <meta charset="utf-8"/> <script src="js/3_2.js"></script> </head> <body> <span>Hello World !</span> <ul id=&q

节点树和元素树--深度遍历

我们在阅读JS高级程序设计的时候,提到了节点树的概念.比如说: elem.parentNode---找elem的父节点: elem.childNodes---找elem的所有的直接子节点: elem.nextSibling---找elem的下一个同辈节点': elem.previousSibling---找elem的上一个同辈节点 因为childNodes包含看不见的空格文本,还有注释等内容,所以使用起来不是太方便. 因此,JS又重新引入了元素树的概念.这个的话,在我们实际应用中,用的比较普遍.

关于树的父子节点的图形化展示

功能需求是实现树的父子节点的图形展示关系,且可以点击节点的时候,会相应地切换显示.因此网上寻找相关的插件来看看是不是满足需求.参考了许多的博客,感觉最有价值的就是这篇博客http://www.cnblogs.com/liuyungao/p/5624163.html,但是我最终也没有选择里面说的插件,最后用了OrgChart,软件的github地址:https://github.com/dabeng/OrgChart. 之前找的那篇博客,自己也稍微研究了一下,但是没有深入,发现有的是不能很契合我的

JS遍历DOM 节点树的实现

本文将分享 DOM 节点树深度遍历.广度遍历代码. 假定我仅遍历 body 且其结构如下: <body> <section class="container"> <div class="left"> <div class="menu"></div> </div> <div class="right"> <div class="b

探索未知种族之osg类生物---状态树与渲染树以及节点树之间的关系

节点树 首先我们来看一个场景构建的实例,并通过它来了解一下“状态节点”StateGraph 和“渲染叶”RenderLeaf 所构成的状态树,“渲染台”RenderStage 和“渲染元”RenderBin 所构成的渲染树,进一步了解这两棵树之间错综复杂的关系,以及理解它们与场景节点树之间更加复杂的关系. 上面是一个虚构的场景结构图,其中叶节点_geode3,以及所有六个几何对象均设置了关联的渲染状 态集(StateSet),且几何体 1 和几何体 2 共享了同一个 StateSet(ss11(

Cocos2d之Node类详解之节点树(二)

一.声明 本文属于笔者原创,允许读者转载和分享,只要注明文章来源即可. 笔者使用cocos2d框架的cocos2d-x-3.3rc0版本的源代码做分析.这篇文章承接上篇<Cocos2d之Node类详解之节点树(一)>. 二.简介 节点 一个Node对象. 节点树 上篇文章介绍到,Node类有一个成员变量 Vector<Node*> _children,这是一个保存所有子节点的数组,因为Node类采用遍历树的方式获取子节点进行渲染,所以我管这两个东西的结合叫节点树. 三.源码详解 &

jquery:树遍历

.children() 获得元素集合中每个匹配元素的子元素,选择器选择性筛选. <!DOCTYPE html> <html> <head> <style> body { font-size:16px; font-weight:bolder; } p { margin:5px 0; } </style> <script src="http://code.jquery.com/jquery-latest.js"><

Cocos2d之Node类详解之节点树(一)

一.声明 笔者分析的是用C++语言实现.版本号为cocos2d-x-3.3rc0的cocos2d框架的源代码.本文为笔者原创,允许读者分享和转载,只要读者注明文章来源即可. 二.简介 Node对象时场景图的基本元素,并且场景图的基本元素必须是Node对象和Node的子类对象.常见的Node类的子类有:Scene.Layer.Sprite.Menu和Label类. Node类主要实现几个特性: Node对象的 addChild(Node *child).getChildByTag(int tag)