在分层查询的每个级别获取计数
Getting counts at each level of a hierarchical query
参考之前的其中一个问题的回答,
Getting counts/totals at each level of a hierarchical query using CONNECT BY
DIRS
====
DIR_ID
PARENT_DIR_ID
DIR_NAME
FILES
=====
FILE_ID
FILE_NAME
DIR_ID
FILE_SIZE
If DIRS contains:
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
Out Out is shown below.
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
我想要一个查询 returns 路径以及层次结构中每个节点中或下方的文件数。基本上是文件数量的汇总。所以查询结果看起来像:
Path File_Count File_Size
===== =========== --------
/ROOT 6 1050
/ROOT/DIR1_1 4 450
/ROOT/DIR1_1/DIR2_1 1 100
/ROOT/DIR1_1/DIR2_2 3 350
/ROOT/DIR1_2 2 600
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
我怎样才能同时获得大小列旁边的文件大小列的计数。
除了文件大小的总和之外,此查询运行良好。
(select count(file_id)
from dirs dc
,files f
where f.dir_id(+) = dc.dir_id
connect by prior dc.dir_id = dc.parent_dir_id
start with dc.dir_id = dp.dir_id
) count,
(select sum(file_size)
from dirs dc
,files f
where f.dir_id(+) = dc.dir_id
connect by prior dc.dir_id = dc.parent_dir_id
start with dc.dir_id = dp.dir_id
) size
from dirs dp
connect by prior dp.dir_id = dp.parent_dir_id
start with dp.parent_dir_id is null
我修改了查询以获取每个级别的文件大小但没有成功。知道缺少什么吗?
我只需要 File_Size 列的计数,如上所示。
想了很多办法,不妨一一列举出来。
子查询方式
这就是您要使用的 - 列出每个目录,为每个目录执行两个递归子查询。我基本上重复了你在这里写的内容,它按预期工作。您的错误是使用保留字 count
和 size
作为列名。
select sys_connect_by_path(dp.dir_name, '/') path,
(select count(file_id)
from dirs dc, files f
where f.dir_id(+) = dc.dir_id
connect by prior dc.dir_id = dc.parent_dir_id
start with dc.dir_id = dp.dir_id
) cnt,
(select sum(file_size)
from dirs dc, files f
where f.dir_id(+) = dc.dir_id
connect by prior dc.dir_id = dc.parent_dir_id
start with dc.dir_id = dp.dir_id
) sz
from dirs dp
connect by prior dp.dir_id = dp.parent_dir_id
start with dp.parent_dir_id is null;
但是,在较大的数据集上,这可能会非常慢。还有其他方法。
直接连接方法
这个不是很有效并且有一些限制,但似乎很容易理解。它对我来说比子查询执行得快一点。
1) 获取完整的目录层次结构
2) 根据 (1) 加入文件以找出每个文件的完整目录名
3) 在 file_dirname like dirname||'%'
上连接 (1) 和 (2) 以获得属于指定目录或其任何子目录的文件列表,然后 group by (1).dir_id
并获得您的总和。
请注意,目录名必须全部以“/”结尾才能正常工作;此外,目录完整路径必须是唯一的。
看起来像这样:
with dirs_r as
(select sys_connect_by_path(dp.dir_name, '/')||'/' path, dir_id
from dirs dp
connect by prior dp.dir_id = dp.parent_dir_id
start with dp.parent_dir_id is null
)
select dirs_r.path, count(*), sum(files_q.file_size)
from dirs_r,
(select d.path, f.file_size
from files f, dirs_r d
where d.dir_id = f.dir_id) files_q
where files_q.path like dirs_r.path||'%'
group by dirs_r.path
order by dirs_r.path
反向处理:
这可能有点难理解,但根据解释计划效率更高,而且它只使用ID,因此更可靠。它的执行速度也比上述两者都快得多。
1) 使用 dp.dir_id = prior dp.parent_dir_id
和 connect_by_root(dir_id)
为每个目录构建一个 reverse 目录层次结构。这样,您就可以获得每个目录 ID 及其所有父目录的行。
2) Join (1) with files,获取每个文件的每个父目录的行。
3) 在 dir_id 上直接加入 (2),然后分组。
select dirs_r.path, count(*), sum(filedir.file_size) from
(select sys_connect_by_path(dp.dir_name, '/') path, dir_id
from dirs dp
connect by prior dp.dir_id = dp.parent_dir_id
start with dp.parent_dir_id is null
) dirs_r,
(select f.file_size, dirs_reverse.dir_id dir_id
from files f,
(select connect_by_root(dp.dir_id) inner_dir_id, dp.dir_id
from dirs dp
connect by dp.dir_id = prior dp.parent_dir_id
) dirs_reverse
where dirs_reverse.inner_dir_id = f.dir_id) filedir
where dirs_r.dir_id = filedir.dir_id
group by dirs_r.path
order by dirs_r.path
参考之前的其中一个问题的回答, Getting counts/totals at each level of a hierarchical query using CONNECT BY
DIRS
====
DIR_ID
PARENT_DIR_ID
DIR_NAME
FILES
=====
FILE_ID
FILE_NAME
DIR_ID
FILE_SIZE
If DIRS contains:
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
Out Out is shown below.
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
我想要一个查询 returns 路径以及层次结构中每个节点中或下方的文件数。基本上是文件数量的汇总。所以查询结果看起来像:
Path File_Count File_Size
===== =========== --------
/ROOT 6 1050
/ROOT/DIR1_1 4 450
/ROOT/DIR1_1/DIR2_1 1 100
/ROOT/DIR1_1/DIR2_2 3 350
/ROOT/DIR1_2 2 600
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
我怎样才能同时获得大小列旁边的文件大小列的计数。
除了文件大小的总和之外,此查询运行良好。
(select count(file_id)
from dirs dc
,files f
where f.dir_id(+) = dc.dir_id
connect by prior dc.dir_id = dc.parent_dir_id
start with dc.dir_id = dp.dir_id
) count,
(select sum(file_size)
from dirs dc
,files f
where f.dir_id(+) = dc.dir_id
connect by prior dc.dir_id = dc.parent_dir_id
start with dc.dir_id = dp.dir_id
) size
from dirs dp
connect by prior dp.dir_id = dp.parent_dir_id
start with dp.parent_dir_id is null
我修改了查询以获取每个级别的文件大小但没有成功。知道缺少什么吗?
我只需要 File_Size 列的计数,如上所示。
想了很多办法,不妨一一列举出来。
子查询方式
这就是您要使用的 - 列出每个目录,为每个目录执行两个递归子查询。我基本上重复了你在这里写的内容,它按预期工作。您的错误是使用保留字 count
和 size
作为列名。
select sys_connect_by_path(dp.dir_name, '/') path,
(select count(file_id)
from dirs dc, files f
where f.dir_id(+) = dc.dir_id
connect by prior dc.dir_id = dc.parent_dir_id
start with dc.dir_id = dp.dir_id
) cnt,
(select sum(file_size)
from dirs dc, files f
where f.dir_id(+) = dc.dir_id
connect by prior dc.dir_id = dc.parent_dir_id
start with dc.dir_id = dp.dir_id
) sz
from dirs dp
connect by prior dp.dir_id = dp.parent_dir_id
start with dp.parent_dir_id is null;
但是,在较大的数据集上,这可能会非常慢。还有其他方法。
直接连接方法
这个不是很有效并且有一些限制,但似乎很容易理解。它对我来说比子查询执行得快一点。
1) 获取完整的目录层次结构
2) 根据 (1) 加入文件以找出每个文件的完整目录名
3) 在 file_dirname like dirname||'%'
上连接 (1) 和 (2) 以获得属于指定目录或其任何子目录的文件列表,然后 group by (1).dir_id
并获得您的总和。
请注意,目录名必须全部以“/”结尾才能正常工作;此外,目录完整路径必须是唯一的。
看起来像这样:
with dirs_r as
(select sys_connect_by_path(dp.dir_name, '/')||'/' path, dir_id
from dirs dp
connect by prior dp.dir_id = dp.parent_dir_id
start with dp.parent_dir_id is null
)
select dirs_r.path, count(*), sum(files_q.file_size)
from dirs_r,
(select d.path, f.file_size
from files f, dirs_r d
where d.dir_id = f.dir_id) files_q
where files_q.path like dirs_r.path||'%'
group by dirs_r.path
order by dirs_r.path
反向处理:
这可能有点难理解,但根据解释计划效率更高,而且它只使用ID,因此更可靠。它的执行速度也比上述两者都快得多。
1) 使用 dp.dir_id = prior dp.parent_dir_id
和 connect_by_root(dir_id)
为每个目录构建一个 reverse 目录层次结构。这样,您就可以获得每个目录 ID 及其所有父目录的行。
2) Join (1) with files,获取每个文件的每个父目录的行。
3) 在 dir_id 上直接加入 (2),然后分组。
select dirs_r.path, count(*), sum(filedir.file_size) from
(select sys_connect_by_path(dp.dir_name, '/') path, dir_id
from dirs dp
connect by prior dp.dir_id = dp.parent_dir_id
start with dp.parent_dir_id is null
) dirs_r,
(select f.file_size, dirs_reverse.dir_id dir_id
from files f,
(select connect_by_root(dp.dir_id) inner_dir_id, dp.dir_id
from dirs dp
connect by dp.dir_id = prior dp.parent_dir_id
) dirs_reverse
where dirs_reverse.inner_dir_id = f.dir_id) filedir
where dirs_r.dir_id = filedir.dir_id
group by dirs_r.path
order by dirs_r.path