将传递闭包表转换为邻接列表

时间:2016-08-29 05:14:22

标签: sql oracle hierarchical-data

我已经实现了传递闭包表格,我称之为GRAPH_TBL。代码

我正在运行Oracle 11gR2。

我想为我的问题提供不完整的数据而道歉。请在下面查看正确且更完整的数据:

我的表

CREATE TABLE "GRAPH_TBL"
("PARENT_NAME" VARCHAR2(80 CHAR), 
"CHILD_NAME" VARCHAR2(80 CHAR), 
"PARENT_ID" VARCHAR2(18 CHAR), 
"CHILD_ID" VARCHAR2(18 CHAR), 
"RELATIVE_LEVEL" NUMBER(18,0)
);

数据:

Insert into GRAPH_TBL PARENT_NAME,CHILD_NAME,PARENT_ID,CHILD_ID,RELATIVE_LEVEL) values ('Components','Components','a044100000171bXAAQ','a044100000171bXAAQ',0);
Insert into GRAPH_TBL (PARENT_NAME,CHILD_NAME,PARENT_ID,CHILD_ID,RELATIVE_LEVEL) values ('Processors','Processors','a044100000171bYAAQ','a044100000171bYAAQ',0);
Insert into GRAPH_TBL (PARENT_NAME,CHILD_NAME,PARENT_ID,CHILD_ID,RELATIVE_LEVEL) values ('Intel','Intel','a044100000171bZAAQ','a044100000171bZAAQ',0);
Insert into GRAPH_TBL (PARENT_NAME,CHILD_NAME,PARENT_ID,CHILD_ID,RELATIVE_LEVEL) values ('Xeon 5600','Xeon 5600','a044100000171bdAAA','a044100000171bdAAA',0);
Insert into GPMETLSTAGE.GRAPH_TBL (PARENT_NAME,CHILD_NAME,PARENT_ID,CHILD_ID,RELATIVE_LEVEL) values ('Intel','Xeon 5600','a044100000171bZAAQ','a044100000171bdAAA',1);
Insert into GRAPH_TBL (PARENT_NAME,CHILD_NAME,PARENT_ID,CHILD_ID,RELATIVE_LEVEL) values ('Processors','Intel','a044100000171bYAAQ','a044100000171bZAAQ',1);
Insert into GRAPH_TBL (PARENT_NAME,CHILD_NAME,PARENT_ID,CHILD_ID,RELATIVE_LEVEL) values ('Processors','Xeon 5600','a044100000171bYAAQ','a044100000171bdAAA',2);
Insert into GRAPH_TBL (PARENT_NAME,CHILD_NAME,PARENT_ID,CHILD_ID,RELATIVE_LEVEL) values ('Xeon 5600','Intel Xeon E5645 2.4Ghz, 12M Cache,Turbo, HT, 1333MHz Max Mem','a044100000171bdAAA','a044100000171grAAA',1);
Insert into GRAPH_TBL (PARENT_NAME,CHILD_NAME,PARENT_ID,CHILD_ID,RELATIVE_LEVEL) values ('Components','Processors','a044100000171bXAAQ','a044100000171bYAAQ',1);
Insert into GRAPH_TBL (PARENT_NAME,CHILD_NAME,PARENT_ID,CHILD_ID,RELATIVE_LEVEL) values ('Eclipse Products and Services','Eclipse Products and Services','a044100000171aQAAQ','a044100000171aQAAQ',0);
Insert into GRAPH_TBL (PARENT_NAME,CHILD_NAME,PARENT_ID,CHILD_ID,RELATIVE_LEVEL) values ('Components','Intel','a044100000171bXAAQ','a044100000171bZAAQ',2);
Insert into GRAPH_TBL (PARENT_NAME,CHILD_NAME,PARENT_ID,CHILD_ID,RELATIVE_LEVEL) values ('Components','Xeon 5600','a044100000171bXAAQ','a044100000171bdAAA',3);
Insert into GRAPH_TBL (PARENT_NAME,CHILD_NAME,PARENT_ID,CHILD_ID,RELATIVE_LEVEL) values ('Eclipse Products and Services','Processors','a044100000171aQAAQ','a044100000171bYAAQ',2);
Insert into GRAPH_TBL (PARENT_NAME,CHILD_NAME,PARENT_ID,CHILD_ID,RELATIVE_LEVEL) values ('Eclipse Products and Services','Intel','a044100000171aQAAQ','a044100000171bZAAQ',3);
Insert into GRAPH_TBL (PARENT_NAME,CHILD_NAME,PARENT_ID,CHILD_ID,RELATIVE_LEVEL) values ('Eclipse Products and Services','Xeon 5600','a044100000171aQAAQ','a044100000171bdAAA',4);
Insert into GRAPH_TBL (PARENT_NAME,CHILD_NAME,PARENT_ID,CHILD_ID,RELATIVE_LEVEL) values ('Eclipse Products and Services','Components','a044100000171aQAAQ','a044100000171bXAAQ',1);
Insert into GRAPH_TBL (PARENT_NAME,CHILD_NAME,PARENT_ID,CHILD_ID,RELATIVE_LEVEL) values ('Intel Xeon E5645 2.4Ghz, 12M Cache,Turbo, HT, 1333MHz Max Mem','Intel Xeon E5645 2.4Ghz, 12M Cache,Turbo, HT, 1333MHz Max Mem','a044100000171grAAA','a044100000171grAAA',0);
commit;

这只是从叶级到树根的一条路径的示例。 所以这个特定的树从顶部到叶节点看起来像这样:

Eclipse Products and Services (this is my root, also some category)
 Components (some category)
  Processors (some category)
   Intel (some category)
    Xeon 5600 (some category)
     Intel Xeon E5645 2.4Ghz, 12M Cache,Turbo, HT, 1333MHz Max Mem (this is my leaf node, product)

相对级别表示类别图的边缘:
0 - 节点本身
1 - 下一个直接直接节点(直接父子关系)
2 - 一跳一跳 3 - 两次跳过 < - 三跳三次

相对级别&gt; = 2仅针对类别定义,但不针对叶子(实际产品)定义

请帮我用SQL将其转换为Adjacency List。 我的预期输出应如下所示:

NAME                                                            ID  PARENT_ID
Eclipse Products and Services                                   a044100000171aQAAQ  null
Components                                                      a044100000171bXAAQ  a044100000171aQAAQ
Processors                                                      a044100000171bYAAQ  a044100000171bXAAQ
Intel                                                           a044100000171bZAAQ  a044100000171bYAAQ
Xeon 5600                                                       a044100000171bdAAA  a044100000171bZAAQ
Intel Xeon E5645 2.4Ghz, 12M Cache,Turbo, HT, 1333MHz Max Mem   a044100000171grAAA  a044100000171bdAAA

感谢您的时间和帮助!

1 个答案:

答案 0 :(得分:0)

试试这个。

with tbl(PARENT_ID,CHILD_ID) as
(select 1,2 from dual union all
select 1,3 from dual union all
select 1,4 from dual union all
select 1,5 from dual union all
select 2,3 from dual union all
select 2,4 from dual union all
select 2,5 from dual union all
select 4,5 from dual
)
select 
    nvl(c.child_id,p.parent_id) as id
    ,c.parent_id
from 
    (select child_id,
    max(parent_id) as parent_id from tbl 
    group by child_id
    ) c
full join
    (select distinct parent_id as parent_id from tbl) p
on c.child_id=p.parent_id
order by id

输出

+----+-----------+
| id | PARENT_ID |
+----+-----------+
|  1 |           |
|  2 |         1 |
|  3 |         2 |
|  4 |         2 |
|  5 |         4 |
+----+-----------+

说明:

第一个派生表cmax(parent)组获得child2,3,4,5。在这种情况下,您将获得孩子1。但由于full join没有孩子,因此不会在输出中给出。为此,您需要distinct parent_id上的parent,这样您才能获得没有child的{​​{1}}。

我们在select子句中需要nvlcoalescecase才能在parent_id {{1}时从派生表p中获取child_id }。