我有一个文件夹树结构,可以扩展到三个层次。所有级别都存储Excel工作表。
为此,我有两个不同的数据库表,第一个存储Excel工作表名称和ID以及文件夹ID,而第二个表存储所有具有各自名称,ID和父文件夹ID的文件夹。
我想显示每个Excel工作表名称及其文件夹,父文件夹和父父文件夹的名称,即使为空。
我尝试用左外部自我连接来做到这一点,但失败了。
表1
DocID DocName FolderId
12345 Abc.xlx 98765
12346 rst.xlx 98764
123457 jkl.xlx 98763
表2
FolderID FolderName ParentFolderId
98765 lmn 98764
98764 pqr 98763
98763 dcg null
所需结果:
DocName ChildFolder Parentfolder Grandparentfolder
abc lmn pqr dcg
rst pqr dcg null
jkl dcg null null
答案 0 :(得分:1)
如果只需要三个文件夹,则可以像下面这样保留三遍联接数据:
-- data
with
sheets(DocID, DocName, FolderId) as (
select 12345, 'Abc.xlx', 98765 from dual union all
select 12346, 'rst.xlx', 98764 from dual union all
select 123457, 'jkl.xlx', 98763 from dual ),
folders(FolderID, FolderName, ParentFolderId) as (
select 98765, 'lmn', 98764 from dual union all
select 98764, 'pqr', 98763 from dual union all
select 98763, 'dcg', null from dual)
-- end of data
select docname, f1.foldername child, f2.foldername parent, f3.foldername grand
from sheets s
left join folders f1 on s.folderid = f1.folderid
left join folders f2 on f2.folderid = f1.parentfolderid
left join folders f3 on f3.folderid = f2.parentfolderid
结果:
DOCNAME CHILD PARENT GRAND
------- ----- ------ -----
Abc.xlx lmn pqr dcg
jkl.xlx dcg
rst.xlx pqr dcg
您还可以使用递归查询,尤其是在嵌套文件夹更多的情况下。
答案 1 :(得分:0)
@PonderStibbons展示了如何使用左外部联接进行此操作。您还可以使用分层查询并调整结果:
with cte (FolderName, BaseFolderId, lvl) as (
select FolderName, connect_by_root(FolderId), level
from table2
connect by FolderId = prior ParentFolderId
)
select *
from (
select t1.DocName,
c.FolderName,
c.lvl
from table1 t1
join cte c on c.BaseFolderId = t1.FolderId
)
pivot (
max(FolderName) for lvl in (1 as ChildFolder, 2 as ParentFolder, 3 as GrandparentFolder)
);
DOCNAME CHILDFOLDER PARENTFOLDER GRANDPARENTFOLDER
------- ----------- ------------ -----------------
jkl.xlx dcg
Abc.xlx lmn pqr dcg
rst.xlx pqr dcg
或使用递归子查询分解而不是层次查询:
with rcte (FolderName, ParentFolderId, BaseFolderId, lvl) as (
select FolderName, ParentFolderId, FolderId, 1 from table2
union all
select t2.FolderName, t2.ParentFolderId, r.BaseFolderId, r.lvl + 1
from rcte r
join table2 t2 on t2.FolderId = r.ParentFolderId
)
select *
from (
select t1.DocName,
r.FolderName,
r.lvl
from table1 t1
join rcte r on r.BaseFolderId = t1.FolderId
)
pivot (
max(FolderName) for lvl in (1 as ChildFolder, 2 as ParentFolder, 3 as GrandparentFolder)
);
DOCNAME CHILDFOLDER PARENTFOLDER GRANDPARENTFOLDER
------- ----------- ------------ -----------------
jkl.xlx dcg
Abc.xlx lmn pqr dcg
rst.xlx pqr dcg
随着您添加更多级别的文件夹,这种方法可能会更好;但是它们都必须在数据透视子句中定义,因此它仍然不完全灵活。
如果您还需要文件夹ID,则将其包含在层次结构/ CTE中,并同时旋转两者:
with rcte (FolderName, FolderId, ParentFolderId, BaseFolderId, lvl) as (
select FolderName, FolderId, ParentFolderId, FolderId, 1 from table2
union all
select t2.FolderName, t2.FolderId, t2.ParentFolderId, r.BaseFolderId, r.lvl + 1
from rcte r
join table2 t2 on t2.FolderId = r.ParentFolderId
)
select *
from (
select t1.DocName,
r.FolderId,
r.FolderName,
r.lvl
from table1 t1
join rcte r on r.BaseFolderId = t1.FolderId
)
pivot (
max(FolderName), max(FolderId) as id
for lvl in (1 as ChildFolder, 2 as ParentFolder, 3 as GrandparentFolder)
);
DOCNAME CHILDFOLDER CHILDFOLDER_ID PARENTFOLDER PARENTFOLDER_ID GRANDPARENTFOLDER GRANDPARENTFOLDER_ID
------- ----------- -------------- ------------ --------------- ----------------- --------------------
jkl.xlx dcg 98763
Abc.xlx lmn 98765 pqr 98764 dcg 98763
rst.xlx pqr 98764 dcg 98763