您的位置:首页 > 数据库 > Oracle

Oracle plsql递归统计所有节点下的子节点&内容个数——start with connect by prior用法

2014-01-13 01:05 966 查看
有些情况下,在存有层级关系的表中,id字段值本身会包含层级关系,例如每两位表示一级。

要想只统计某个或某几个层级节点下子节点+内容个数,就需要使用类似like ‘01%’的过滤条件即可。

例如select count(1) from test_category t where t.cid like '01%' or t.cid like '02%‘;

但是,如果id值本身无法表示层级关系,那么必须使用如下方法,即使是只统计某个或某几个层级节点下子节点+内容个数。

/**递归查询

已知,

节点下可以挂子节点或者内容,

叶子节点下只能挂内容,

内容下不能挂节点。

要统计每个节点下的内容个数(包括自己的内容和子节点的内容)

*/

----测试数据

--节点表

create table test_category(

cid varchar2(20), 

parentid varchar2(20)

);

--内容记录表

create table test_category2content(

cateid varchar2(20),

contid varchar2(20),

record_date varchar(8)

);

--分支1

insert into test_category values('1', '0');

insert into test_category values('11', '1');

insert into test_category values('12', '1');----叶子节点

insert into test_category values('111', '11');----叶子节点

insert into test_category values('112', '11');

insert into test_category2content values('1', 'X', '20170606');

insert into test_category2content values('1', 'X', '20170607');

insert into test_category2content values('11', 'X', '20170606');

insert into test_category2content values('11', 'X', '20170607');

insert into test_category2content values('12', 'X', '20170606');

insert into test_category2content values('12', 'X', '20170607');

insert into test_category2content values('111', 'X', '20170606');

insert into test_category2content values('111', 'X', '20170607');

insert into test_category2content values('111', 'X', '20170608');

---分支2

--insert into test_category2content values('2', 'X', '20170606');

--insert into test_category2content values('21', 'X', '20170607');

--insert into test_category values('2', '0');

--insert into test_category values('21', '2');

--insert into test_category values('211', '21');----设为叶子节点

commit;

---结果:

--1:9

--11:5

--12:2

--111:3

--112:0

----正确的做法

select x.cid

  , (

    select sum(nvl(t2.amount, 0))--t1.cid, nvl(t2.amount, 0) as amount

 from test_category t1 left join

         (select cateid, count(1) as amount from test_category2content group by cateid) t2

        on t1.cid = t2.cateid

    start with t1.cid = x.cid

    connect by prior t1.cid = t1.parentid

  ) as cc 

from test_category x

;

---如果要统计给定日期(例如20170606)的各个节点下的子节点个数,就需要加上where语句

(下面这段语句是根据我项目中使用到的sql语句进行改写的,没有调测过)

select x.cid

  , '20170606' as datet

  , (

    select sum(nvl(t2.amount, 0))--t1.cid, nvl(t2.amount, 0) as amount

    from test_category t1 left join 

        (select cateid

                 , record_date as datet

                 , count(1) as amount from test_category2content group by cateid, record_date) t2

        on t1.cid = t2.cateid

    where t2.datet = '20170606'-----added 

    start with t1.cid = x.cid

    connect by prior t1.cid = t1.parentid

  ) as cc

from test_category x

;

----//====稍微研究下connect by的作用

---从parentid到cid开始递归,并以parentid为主展示这条记录

select t1.parentid, t1.cid, level

from test_category t1

start with t1.parentid = 1

connect by prior t1.parentid = t1.cid

;

---从parentid到cid开始递归,并以parentid为主展示这条记录

select t1.parentid, t1.cid, level

from test_category t1

start with t1.cid = 1

connect by prior t1.parentid = t1.cid

;

---从parentid到cid开始递归,并以cid为主展示这条记录

select t1.cid, t1.parentid, level

from test_category t1

start with t1.parentid = 1

connect by t1.parentid = prior t1.cid

;

---从parentid到cid开始递归,并以cid为主展示这条记录

select t1.cid, t1.parentid, level

from test_category t1

start with t1.cid = 1

connect by t1.parentid = prior t1.cid

;

















                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: