Получение каждого родителя в иерархии подряд - PullRequest
0 голосов
/ 17 апреля 2019

У меня есть структура дерева папок, которая может доходить до трех уровней. На всех уровнях хранятся листы Excel.

Для этого у меня есть две разные таблицы базы данных, первая из которых хранит имя и идентификатор листа Excel вместе с идентификатором папки, а во второй таблице хранятся все папки с соответствующими именами, идентификаторами и идентификаторами родительских папок.

Я хочу отобразить каждое имя листа 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 ]

1 голос
/ 17 апреля 2019

Если вам нужно ровно три папки, то вы можете трижды соединить данные, как здесь:

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

Вы также можете использовать рекурсивный запрос, особенно еслибольше вложенных папок.

0 голосов
/ 17 апреля 2019

@ 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                           

дб <> скрипка

Такой подход может быть лучше, если вы добавите больше уровней папок; но все они должны быть определены в предложении pivot, поэтому он все еще не полностью гибок.


Если вы хотите также идентификаторы папок, включите их в иерархию / 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                                       

Обновлен дБ <> скрипка

...