免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 9564 | 回复: 17
打印 上一主题 下一主题

求一个取得一棵树的所有孩子节点的sql文 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-05-03 16:45 |只看该作者 |倒序浏览
在工作中遇到一个问题,关于取得一棵树的所有孩子节点.
脑袋想破了,也没有想起解决方法.特来请教大侠们.
谢谢!

个表结构如下:
    id    | parent | flag
--------+-------- +--------
1011    101        5
1012    101        5
101      10          2
10        1            1
1                        7

想得到的结果如下:
1.当flag=5时,结果:
  oldid  |    id    | parent | flag
---------+--------+-------- +--------
1011           1011    101        5
1012           1012    101        5

2.当flag=2时,结果:

oldid    |    id    | parent | flag
---------+--------+-------- +--------
101        1011    101        5
101        1012    101        5
101        101      10          2


3.当flag=1时,结果:

oldid    |    id    | parent | flag
---------+--------+-------- +--------
10          1011    101        5
10          1012    101        5
10          101      10          2
10          10        1            1

也就是当指定flag时,
先查出对应的id,再以这个id去查询下面所有的子节点.
最后出来的数据,第一列数据,就是先查出来的id.


flag 最好用in的方式
如flag in ('1','3','5')

论坛徽章:
0
2 [报告]
发表于 2011-05-03 16:52 |只看该作者
建立测试表:
CREATE TABLE testtable
(
  id character varying(20) NOT NULL,
  parent character varying(20),
  flag character(1)
)
插入数据:
insert into testtable(id,parent,flag) values('1011','101','5');
insert into testtable(id,parent,flag) values('1012','101','5');
insert into testtable(id,parent,flag) values('101','10','2');
insert into testtable(id,parent,flag) values('10','1','1');
insert into testtable(id,parent,flag) values('1',null,'7');

论坛徽章:
4
丑牛
日期:2014-09-15 09:28:12双子座
日期:2014-12-19 17:01:192015年辞旧岁徽章
日期:2015-03-03 16:54:15数据库技术版块每日发帖之星
日期:2016-06-28 06:20:00
3 [报告]
发表于 2011-05-03 16:57 |只看该作者
这个需要用 function 吧, 一个SQL估计不行。

论坛徽章:
0
4 [报告]
发表于 2011-05-03 16:59 |只看该作者
本帖最后由 yanxt 于 2011-05-03 17:05 编辑

用function 或者 存储过程都可以.
唉!
对PostgreSQL 不熟,不会写!

在PostgreSQL8.4版本以后,
新增了递归功能.
如:
WITH RECURSIVE r AS (
       SELECT * FROM test WHERE flag in ('1','3','5')
     union   ALL
       SELECT test.* FROM test, r WHERE test.parent = r.id
     )
SELECT * FROM r ORDER BY id;

但是oldid如何加上去呢?

谢谢

论坛徽章:
1
数据库技术版块每日发帖之星
日期:2015-06-20 22:20:00
5 [报告]
发表于 2011-05-03 22:20 |只看该作者
这个我通常在程序中实现,用遍历或递归的方法,用到很多SQL,很笨的算法,如果单单依靠pg或者sql,是有点难度。不过楼上你既然想到了思路,多试试。
弄好了,公布一下,为这事,我十分苦恼,一直无好的算法。
会的朋友,支一下招。

论坛徽章:
0
6 [报告]
发表于 2011-05-05 13:19 |只看该作者
本帖最后由 yanxt 于 2011-05-06 10:45 编辑

解决了.

第一步:
         建立一个游标.
         test_cursor cursor for
         selet *
         from testtable;
第二步:
         打开游标进行循环.
        LOOP
            FETCH test_cursor INTO test_ROW;
            EXIT WHEN NOT FOUND;
        if test_ROW.flag in ('1','3','5') then
               WITH RECURSIVE r AS (
                      SELECT * FROM test WHERE r.id =test_ROW.id
                     union   ALL
                      SELECT test.* FROM test, r WHERE test.parent = r.id
                    )
               SELECT test_ROW.id,* FROM r ORDER BY id;
        end if;
        END LOOP;
        CLOSE test_cursor ;

利用系统提供的功能,效率有很大的提高,代码也少了很多!

论坛徽章:
1
寅虎
日期:2013-09-29 23:15:15
7 [报告]
发表于 2011-05-05 15:02 |只看该作者
学习!

论坛徽章:
1
寅虎
日期:2013-09-29 23:15:15
8 [报告]
发表于 2011-05-05 15:03 |只看该作者
学习!!

论坛徽章:
59
2015七夕节徽章
日期:2015-08-24 11:17:25ChinaUnix专家徽章
日期:2015-07-20 09:19:30每周论坛发贴之星
日期:2015-07-20 09:19:42ChinaUnix元老
日期:2015-07-20 11:04:38荣誉版主
日期:2015-07-20 11:05:19巳蛇
日期:2015-07-20 11:05:26CU十二周年纪念徽章
日期:2015-07-20 11:05:27IT运维版块每日发帖之星
日期:2015-07-20 11:05:34操作系统版块每日发帖之星
日期:2015-07-20 11:05:36程序设计版块每日发帖之星
日期:2015-07-20 11:05:40数据库技术版块每日发帖之星
日期:2015-07-20 11:05:432015年辞旧岁徽章
日期:2015-07-20 11:05:44
9 [报告]
发表于 2011-05-05 15:20 |只看该作者
还是O强,直接就可以树出来。PG没有这样的功能吗?

论坛徽章:
0
10 [报告]
发表于 2011-05-06 10:49 |只看该作者
有.
如:
------------------------------------------------------------------------------------------------
               WITH RECURSIVE r AS (
                      SELECT * FROM test WHERE r.id =查询结点
                     union   ALL
                      SELECT * FROM test, r WHERE test.parent = r.id
                    )
               SELECT * FROM r ORDER BY id;
-------------------------------------------------------------------------------------------------
不知道有没有更好的方法?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP