我对此感到很沮丧。我正在尝试针对具有递归关系(分层)的表编写查询(使用Oracle),并获取存储在树中每个节点下方的另一个表中的记录总数。另一个表只有与叶节点相关的记录。但是,我希望得到树中每个节点及其下方的总计。例如,假设我有两张桌子。 DIRS包含目录名称和标识目录结构的递归关系,FILES包含带有DIRS外键的文件信息,指示文件所在的目录:
DIRS
====
DIR_ID
PARENT_DIR_ID
DIR_NAME
FILES
=====
FILE_ID
FILE_NAME
DIR_ID
FILE_SIZE
如果DIRS包含:
DIR_ID PARENT_DIR_ID DIR_NAME
====== ============= ========
1 ROOT
2 1 DIR1_1
3 1 DIR1_2
4 2 DIR2_1
5 2 DIR2_2
和FILES包含
FILE_ID FILE_NAME DIR_ID FILE_SIZE
======= ========= ====== =========
1 test1.txt 5 100
2 test2.txt 5 200
3 test5.txt 5 50
4 test3.txt 3 300
5 test4.txt 3 300
6 test6.txt 4 100
我想要一个返回路径的查询以及层次结构中每个节点中或下面的文件数。基本上是文件数量的汇总。因此查询结果如下所示:
Path File_Count
===== ===========
/ROOT 6
/ROOT/DIR1_1 4
/ROOT/DIR1_1/DIR2_1 1
/ROOT/DIR1_1/DIR2_2 3
/ROOT/DIR1_2 2
更新 SQL脚本,用于创建包含与上述内容匹配的示例数据的表:
create table DIRS (dir_id number(38) primary key
, parent_dir_id number(38) null references DIRS(dir_id)
, dir_name varchar2(128) not null);
create table FILES (file_id number(38) primary key
, file_name varchar2(128) not null
, dir_id number(38) not null references DIRS(dir_id)
, file_size number not null
, unique (dir_id, file_name));
insert into DIRS
select 1, null, 'ROOT' from dual
union all select 2, 1, 'DIR1_1' from dual
union all select 3, 1, 'DIR1_2' from dual
union all select 4, 2, 'DIR2_1' from dual
union all select 5, 2, 'DIR2_2' from dual;
insert into files
select 1, 'test1.txt', 5, 100 from dual
union all select 2, 'test2.txt', 5, 200 from dual
union all select 3, 'test5.txt', 5, 50 from dual
union all select 4, 'test3.txt', 3, 300 from dual
union all select 5, 'test4.txt', 3, 300 from dual
union all select 6, 'test6.txt', 4, 100 from dual;
commit;
答案 0 :(得分:4)
这个很简单:
09:38:54 HR@vm_xe> l
1 select sys_connect_by_path(dp.dir_name, '/') path
2 ,(select count(file_id)
3 from dirs dc
4 ,files f
5 where f.dir_id(+) = dc.dir_id
6 connect by prior dc.dir_id = dc.parent_dir_id
7 start with dc.dir_id = dp.dir_id
8 ) count
9 from dirs dp
10 connect by prior dp.dir_id = dp.parent_dir_id
11* start with dp.parent_dir_id is null
09:38:55 HR@vm_xe> /
PATH COUNT
------------------------------ ----------
/ROOT 6
/ROOT/DIR1_1 4
/ROOT/DIR1_1/DIR2_1 1
/ROOT/DIR1_1/DIR2_2 3
/ROOT/DIR1_2 2
5 rows selected.
Elapsed: 00:00:00.02
答案 1 :(得分:1)
select sys_connect_by_path(D.dir_name, '/'), S.count_distinct_file_id
from DIRS D
inner join (select subtree_root_dir_id
, count(distinct file_id) count_distinct_file_id
from (select distinct connect_by_root D.DIR_ID subtree_root_dir_id
, F.file_id
from DIRS D
left outer join FILES F on F.dir_id = D.dir_id
start with 1=1 connect by prior D.dir_id = D.parent_dir_id)
group by subtree_root_dir_id) S
on D.dir_id = S.subtree_root_dir_id
start with D.dir_id = 1 connect by prior D.dir_id = D.parent_dir_id
给出你要求的结果,但我的直觉说我没有看到什么,而且查询可以更简单。 (请不接受这个答案,直到几天过去,希望有人提出更好的答案。)