连续获取层次结构中的每个父级

时间:2019-04-17 09:50:51

标签: oracle recursion hierarchy

我有一个文件夹树结构,可以扩展到三个层次。所有级别都存储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

2 个答案:

答案 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                           

db<>fiddle

随着您添加更多级别的文件夹,这种方法可能会更好;但是它们都必须在数据透视子句中定义,因此它仍然不完全灵活。


如果您还需要文件夹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                                       

Updated db<>fiddle

相关问题