zoukankan      html  css  js  c++  java
  • (转)父子节点遍历

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://qianzhang.blog.51cto.com/317608/1205679

    对于树/图的遍历,通常有2种算法来实现:迭代(Iteration)和递归(Recursion),迭代就是利用循环反复取值/赋值的过程;递归则是反复自己调用自己来获得最终结果。

    不过SQL Server里的递归有32层嵌套限制,目的在于防止代码进入死循环。除非使用提示OPTION (MAXRECURSION 0)

    测试数据:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    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来向下查找

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    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来逐层查找

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    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) 自定义函数递归

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    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递归

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    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就可以了

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    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) 自定义函数递归

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    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递归

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    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
  • 相关阅读:
    PHP中使用CURL实现Get和Post请求方法
    编码规范
    session跨域共享问题解决方案
    第二十七节 新增语义标签
    第二十六节 屏幕适配之rem单位
    第二十五节 屏幕适配之em单位
    第二十四节 屏幕适配之响应式布局
    第二十三节 屏幕适配之流体布局
    第二十二节 屏幕适配之适配布局类型
    第二十一节 屏幕适配之背景图尺寸的设置
  • 原文地址:https://www.cnblogs.com/Luouy/p/3173989.html
Copyright © 2011-2022 走看看