【问题标题】:Getting each parent in hierarchy in a row连续获取层次结构中的每个父级
【发布时间】:2019-09-07 12:52:15
【问题描述】:

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

【问题讨论】:

  • 格式化您的问题,使其更具可读性

标签: oracle recursion hierarchy


【解决方案1】:

@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

当您添加更多级别的文件夹时,这种方法可能会更好;但是它们都必须在 pivot 子句中定义,所以它仍然不完全灵活。


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

【讨论】:

  • 谢谢,我试过了,结果符合预期,但如果我们希望所有涉及的文件夹的 ID 也被存储@Alex Poole,我无法添加到它
  • 不确定你的意思。如果您有更多级别的文件夹,则需要扩展枢轴的 in 子句以包含这些文件夹。
  • 不,我说的不是关卡。我说的是获取所有文件夹的 ID 以及名称
  • @AlphaQ - 我明白了,你的问题并没有表明你想要这些 ID。我添加了一种方法来使用相同的机制来展示它们。
  • 我在 CTE 中添加了,也许我做错了什么。谢谢,我会检查的。
【解决方案2】:

如果您只想要三个文件夹,那么您可以像这里一样将连接数据留下三次:

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

您还可以使用递归查询,尤其是在嵌套文件夹较多的情况下。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    • 2015-07-28
    • 2020-05-29
    • 1970-01-01
    • 2012-12-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多