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
;
要想只统计某个或某几个层级节点下子节点+内容个数,就需要使用类似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
;
相关文章推荐
- 使用oracle的start with... connect by prior根据子节点,找到从子节点到根目录所有路径
- Oracle start with..Connect By prior..用法实例讲解
- Oracle start with connect by prior 递归查询用法
- Oracle_start_with_connect_by_prior_用法
- start with connect by prior 递归查询用法
- Oracle中START WITH...CONNECT BY PRIOR用法
- oracle 中的select ...connect by prior ...start with 及(+)的用法
- oracle 的start with connect by prior 的用法
- start with connect by prior 递归查询用法
- start with connect by prior 递归查询用法
- start with connect by prior 递归查询用法
- 通过START WITH 和CONNECT BY PRIOR遍历上级父节点(上级目录)
- Oracle start with connect by prior 用法
- ORACLE start with… connect by prior 子句用法
- start with...connect by prior用法 【转】
- start with connect by prior 递归查询用法
- Oracle start with connect by prior 用法(递归查询树形结构)
- Oracle START WITH...CONNECT BY PRIOR的用法
- oracle start with connect by prior 递归查询用法
- Oracle start with connect by prior 用法