从 Oracle 表构建树
Build a tree from Oracle tables
我在 Oracle 中有两个 tables 用于表示各种树,tables 是: "PARTS_TREE_ENTRIES" 存储所有节点(包括 parents 和 children) 和 "PARTS_ITEMS" 描述节点之间的关系
在 table TREE_ITEMS 列中 COMPONENT_ID 代表父亲 COMPONENT_ITEMID 它的 child
不止一棵树,所有树的节点都在同一个table "TREE_ENTRIES"为了更容易理解,这是一对树的表示:
这些是他们在 table 中的条目:
正如您在 table TREE_ITEMS 中看到的那样,作为分支根的节点对于 COMPONENT_ID
具有值 "A"
我需要帮助来构建查询以获取最后一级所有节点及其 parents 及其 ID 的列表,输出应类似于以下内容:
我读过 "Connect by" 条款,但我从未使用过它,也不知道从哪里开始。
非常感谢您!
我知道您明确询问了有关按查询连接的问题,但我认为我们可以练习使用 Recursive With SQL,因为它可以完成相同的工作并增加一些功能。
根据您的示例结果,我的最佳猜测是这样的。
我不清楚您是想要串联数据还是分隔列,所以我们对这两种情况都有建议。
with tree_view(tree_id, component_id, component_itemid, id, part_tree_id, componentid, name, lvl, tree_path, root_id) as (
select t.tree_id, t.component_id, t.component_itemid, t.id, e.part_tree_id, e.componentid, e.name, 1, e.name, component_itemid
from tree_items t,
tree_entries e
where t.component_itemid = e.componentid
and t.tree_id = e.part_tree_id
and t.component_id = 'A'
union all
select t.tree_id, t.component_id, t.component_itemid, t.id, e.part_tree_id, e.componentid, e.name, tv.lvl + 1, tv.tree_path || '=>' || e.name, tv.root_id
from tree_items t,
tree_entries e,
tree_view tv
where to_char(tv.component_itemid) = to_char(t.component_id)
and to_char(e.componentid) = to_char(t.component_itemid)
and tv.tree_id = t.tree_id
) -- end of hierarchy view
search depth first by lvl set order1
select tree_path,
name,
componentid,
regexp_substr(tree_path, '[[:alpha:]]+', 1, 1) lvl1_part,
regexp_substr(tree_path, '[[:alpha:]]+', 1, 2) lvl2_part,
regexp_substr(tree_path, '[[:alpha:]]+', 1, 3) lvl3_part -- add more if there are further levels down the tree
from (
select tree_id, component_id, component_itemid, id, part_tree_id, componentid, name, lvl, tree_path, root_id, order1,
case when lvl - lead(lvl) over (order by order1) < 0 then 0 else 1 end is_leaf
from tree_view
)
where is_leaf = 1;
这是使用您提供的数据在 Oracle 上执行的示例:
Connected to Oracle Database 11g Enterprise Edition Release 11.2.0.4.0
Connected as sitja@orasitja
SQL>
SQL> col tree_path format a40
SQL> col lvl1_part format a20
SQL> col lvl2_part format a20
SQL> col lvl3_part format a20
SQL> drop table tree_entries;
Table dropped
SQL> create table tree_entries as
2 with tree_entries(part_tree_id, componentid, name) as (
3 select 1, 101, 'CLOCK' from dual union all
4 select 1, 102, 'WATCH' from dual union all
5 select 1, 105, 'BAND' from dual union all
6 select 1, 113, 'MATERIAL' from dual union all
7 select 1, 114, 'COLOR' from dual union all
8 select 1, 106, 'CASE' from dual union all
9 select 1, 115, 'MATERIAL' from dual union all
10 select 1, 116, 'SHAPE' from dual union all
11 select 1, 107, 'BEZEL' from dual union all
12 select 1, 117, 'MATERIAL' from dual union all
13 select 1, 118, 'TEXTURE' from dual union all
14 select 1, 108, 'FACE' from dual union all
15 select 1, 119, 'SHAPE' from dual union all
16 select 1, 120, 'DESIGN' from dual union all
17 select 2, 103, 'RELOJ' from dual union all
18 select 2, 104, 'RELOJPULSERA' from dual union all
19 select 2, 109, 'CORREA' from dual union all
20 select 2, 121, 'MATERIAL' from dual union all
21 select 2, 122, 'COLOR' from dual union all
22 select 2, 110, 'CAJA' from dual union all
23 select 2, 123, 'MATERIAL' from dual union all
24 select 2, 124, 'FORMA' from dual union all
25 select 2, 111, 'BISEL' from dual union all
26 select 2, 125, 'MATERIAL' from dual union all
27 select 2, 126, 'TEXTURA' from dual union all
28 select 2, 112, 'CARATULA' from dual union all
29 select 2, 127, 'FORMA' from dual union all
30 select 2, 128, 'DISEÑO' from dual
31 )
32 select * from tree_entries;
Table created
SQL> drop table tree_items;
Table dropped
SQL> create table tree_items as
2 with tree_items(tree_id, component_id, component_itemid, id) as (
3 select 1, 'A', 101, 1 from dual union all
4 select 1, 'A', 102, 2 from dual union all
5 select 1, '101', 107, 3 from dual union all
6 select 1, '101', 108, 4 from dual union all
7 select 1, '102', 105, 5 from dual union all
8 select 1, '102', 106, 6 from dual union all
9 select 1, '107', 117, 7 from dual union all
10 select 1, '107', 118, 8 from dual union all
11 select 1, '108', 119, 9 from dual union all
12 select 1, '108', 120, 10 from dual union all
13 select 1, '105', 113, 11 from dual union all
14 select 1, '105', 114, 12 from dual union all
15 select 1, '106', 115, 13 from dual union all
16 select 1, '106', 116, 14 from dual union all
17 select 2, 'A', 103, 15 from dual union all
18 select 2, 'A', 104, 26 from dual union all
19 select 2, '103', 111, 33 from dual union all
20 select 2, '103', 112, 42 from dual union all
21 select 2, '104', 109, 54 from dual union all
22 select 2, '104', 110, 62 from dual union all
23 select 2, '111', 125, 74 from dual union all
24 select 2, '111', 126, 82 from dual union all
25 select 2, '112', 127, 91 from dual union all
26 select 2, '112', 128, 10 from dual union all
27 select 2, '109', 127, 114 from dual union all
28 select 2, '109', 122, 122 from dual union all
29 select 2, '110', 123, 3334 from dual union all
30 select 2, '110', 124, 141 from dual
31 )
32 select * from tree_items;
Table created
SQL> with tree_view(tree_id, component_id, component_itemid, id, part_tree_id, componentid, name, lvl, tree_path, root_id) as (
2 select t.tree_id, t.component_id, t.component_itemid, t.id, e.part_tree_id, e.componentid, e.name, 1, e.name, component_itemid
3 from tree_items t,
4 tree_entries e
5 where t.component_itemid = e.componentid
6 and t.tree_id = e.part_tree_id
7 and t.component_id = 'A'
8 union all
9 select t.tree_id, t.component_id, t.component_itemid, t.id, e.part_tree_id, e.componentid, e.name, tv.lvl + 1, tv.tree_path || '=>' || e.name, tv.root_id
10 from tree_items t,
11 tree_entries e,
12 tree_view tv
13 where to_char(tv.component_itemid) = to_char(t.component_id)
14 and to_char(e.componentid) = to_char(t.component_itemid)
15 and tv.tree_id = t.tree_id
16 ) -- end of hierarchy view
17 search depth first by lvl set order1
18 select tree_path,
19 name,
20 componentid,
21 regexp_substr(tree_path, '[[:alpha:]]+', 1, 1) lvl1_part,
22 regexp_substr(tree_path, '[[:alpha:]]+', 1, 2) lvl2_part,
23 regexp_substr(tree_path, '[[:alpha:]]+', 1, 3) lvl3_part -- add more if there are further levels down the tree
24 from (
25 select tree_id, component_id, component_itemid, id, part_tree_id, componentid, name, lvl, tree_path, root_id, order1,
26 case when lvl - lead(lvl) over (order by order1) < 0 then 0 else 1 end is_leaf
27 from tree_view
28 )
29 where is_leaf = 1;
TREE_PATH NAME COMPONENTID LVL1_PART LVL2_PART LVL3_PART
---------------------------------------- ------------ ----------- -------------------- -------------------- --------------------
CLOCK=>BEZEL=>MATERIAL MATERIAL 117 CLOCK BEZEL MATERIAL
CLOCK=>BEZEL=>TEXTURE TEXTURE 118 CLOCK BEZEL TEXTURE
CLOCK=>FACE=>SHAPE SHAPE 119 CLOCK FACE SHAPE
CLOCK=>FACE=>DESIGN DESIGN 120 CLOCK FACE DESIGN
WATCH=>BAND=>MATERIAL MATERIAL 113 WATCH BAND MATERIAL
WATCH=>BAND=>COLOR COLOR 114 WATCH BAND COLOR
WATCH=>CASE=>MATERIAL MATERIAL 115 WATCH CASE MATERIAL
WATCH=>CASE=>SHAPE SHAPE 116 WATCH CASE SHAPE
RELOJ=>BISEL=>MATERIAL MATERIAL 125 RELOJ BISEL MATERIAL
RELOJ=>BISEL=>TEXTURA TEXTURA 126 RELOJ BISEL TEXTURA
RELOJ=>CARATULA=>FORMA FORMA 127 RELOJ CARATULA FORMA
RELOJ=>CARATULA=>DISEÑO DISEÑO 128 RELOJ CARATULA DISEÑO
RELOJPULSERA=>CORREA=>COLOR COLOR 122 RELOJPULSERA CORREA COLOR
RELOJPULSERA=>CORREA=>FORMA FORMA 127 RELOJPULSERA CORREA FORMA
RELOJPULSERA=>CAJA=>MATERIAL MATERIAL 123 RELOJPULSERA CAJA MATERIAL
RELOJPULSERA=>CAJA=>FORMA FORMA 124 RELOJPULSERA CAJA FORMA
16 rows selected
SQL>
我在 Oracle 中有两个 tables 用于表示各种树,tables 是: "PARTS_TREE_ENTRIES" 存储所有节点(包括 parents 和 children) 和 "PARTS_ITEMS" 描述节点之间的关系
在 table TREE_ITEMS 列中 COMPONENT_ID 代表父亲 COMPONENT_ITEMID 它的 child
不止一棵树,所有树的节点都在同一个table "TREE_ENTRIES"为了更容易理解,这是一对树的表示:
这些是他们在 table 中的条目:
正如您在 table TREE_ITEMS 中看到的那样,作为分支根的节点对于 COMPONENT_ID
具有值 "A"我需要帮助来构建查询以获取最后一级所有节点及其 parents 及其 ID 的列表,输出应类似于以下内容:
我读过 "Connect by" 条款,但我从未使用过它,也不知道从哪里开始。
非常感谢您!
我知道您明确询问了有关按查询连接的问题,但我认为我们可以练习使用 Recursive With SQL,因为它可以完成相同的工作并增加一些功能。
根据您的示例结果,我的最佳猜测是这样的。
我不清楚您是想要串联数据还是分隔列,所以我们对这两种情况都有建议。
with tree_view(tree_id, component_id, component_itemid, id, part_tree_id, componentid, name, lvl, tree_path, root_id) as (
select t.tree_id, t.component_id, t.component_itemid, t.id, e.part_tree_id, e.componentid, e.name, 1, e.name, component_itemid
from tree_items t,
tree_entries e
where t.component_itemid = e.componentid
and t.tree_id = e.part_tree_id
and t.component_id = 'A'
union all
select t.tree_id, t.component_id, t.component_itemid, t.id, e.part_tree_id, e.componentid, e.name, tv.lvl + 1, tv.tree_path || '=>' || e.name, tv.root_id
from tree_items t,
tree_entries e,
tree_view tv
where to_char(tv.component_itemid) = to_char(t.component_id)
and to_char(e.componentid) = to_char(t.component_itemid)
and tv.tree_id = t.tree_id
) -- end of hierarchy view
search depth first by lvl set order1
select tree_path,
name,
componentid,
regexp_substr(tree_path, '[[:alpha:]]+', 1, 1) lvl1_part,
regexp_substr(tree_path, '[[:alpha:]]+', 1, 2) lvl2_part,
regexp_substr(tree_path, '[[:alpha:]]+', 1, 3) lvl3_part -- add more if there are further levels down the tree
from (
select tree_id, component_id, component_itemid, id, part_tree_id, componentid, name, lvl, tree_path, root_id, order1,
case when lvl - lead(lvl) over (order by order1) < 0 then 0 else 1 end is_leaf
from tree_view
)
where is_leaf = 1;
这是使用您提供的数据在 Oracle 上执行的示例:
Connected to Oracle Database 11g Enterprise Edition Release 11.2.0.4.0
Connected as sitja@orasitja
SQL>
SQL> col tree_path format a40
SQL> col lvl1_part format a20
SQL> col lvl2_part format a20
SQL> col lvl3_part format a20
SQL> drop table tree_entries;
Table dropped
SQL> create table tree_entries as
2 with tree_entries(part_tree_id, componentid, name) as (
3 select 1, 101, 'CLOCK' from dual union all
4 select 1, 102, 'WATCH' from dual union all
5 select 1, 105, 'BAND' from dual union all
6 select 1, 113, 'MATERIAL' from dual union all
7 select 1, 114, 'COLOR' from dual union all
8 select 1, 106, 'CASE' from dual union all
9 select 1, 115, 'MATERIAL' from dual union all
10 select 1, 116, 'SHAPE' from dual union all
11 select 1, 107, 'BEZEL' from dual union all
12 select 1, 117, 'MATERIAL' from dual union all
13 select 1, 118, 'TEXTURE' from dual union all
14 select 1, 108, 'FACE' from dual union all
15 select 1, 119, 'SHAPE' from dual union all
16 select 1, 120, 'DESIGN' from dual union all
17 select 2, 103, 'RELOJ' from dual union all
18 select 2, 104, 'RELOJPULSERA' from dual union all
19 select 2, 109, 'CORREA' from dual union all
20 select 2, 121, 'MATERIAL' from dual union all
21 select 2, 122, 'COLOR' from dual union all
22 select 2, 110, 'CAJA' from dual union all
23 select 2, 123, 'MATERIAL' from dual union all
24 select 2, 124, 'FORMA' from dual union all
25 select 2, 111, 'BISEL' from dual union all
26 select 2, 125, 'MATERIAL' from dual union all
27 select 2, 126, 'TEXTURA' from dual union all
28 select 2, 112, 'CARATULA' from dual union all
29 select 2, 127, 'FORMA' from dual union all
30 select 2, 128, 'DISEÑO' from dual
31 )
32 select * from tree_entries;
Table created
SQL> drop table tree_items;
Table dropped
SQL> create table tree_items as
2 with tree_items(tree_id, component_id, component_itemid, id) as (
3 select 1, 'A', 101, 1 from dual union all
4 select 1, 'A', 102, 2 from dual union all
5 select 1, '101', 107, 3 from dual union all
6 select 1, '101', 108, 4 from dual union all
7 select 1, '102', 105, 5 from dual union all
8 select 1, '102', 106, 6 from dual union all
9 select 1, '107', 117, 7 from dual union all
10 select 1, '107', 118, 8 from dual union all
11 select 1, '108', 119, 9 from dual union all
12 select 1, '108', 120, 10 from dual union all
13 select 1, '105', 113, 11 from dual union all
14 select 1, '105', 114, 12 from dual union all
15 select 1, '106', 115, 13 from dual union all
16 select 1, '106', 116, 14 from dual union all
17 select 2, 'A', 103, 15 from dual union all
18 select 2, 'A', 104, 26 from dual union all
19 select 2, '103', 111, 33 from dual union all
20 select 2, '103', 112, 42 from dual union all
21 select 2, '104', 109, 54 from dual union all
22 select 2, '104', 110, 62 from dual union all
23 select 2, '111', 125, 74 from dual union all
24 select 2, '111', 126, 82 from dual union all
25 select 2, '112', 127, 91 from dual union all
26 select 2, '112', 128, 10 from dual union all
27 select 2, '109', 127, 114 from dual union all
28 select 2, '109', 122, 122 from dual union all
29 select 2, '110', 123, 3334 from dual union all
30 select 2, '110', 124, 141 from dual
31 )
32 select * from tree_items;
Table created
SQL> with tree_view(tree_id, component_id, component_itemid, id, part_tree_id, componentid, name, lvl, tree_path, root_id) as (
2 select t.tree_id, t.component_id, t.component_itemid, t.id, e.part_tree_id, e.componentid, e.name, 1, e.name, component_itemid
3 from tree_items t,
4 tree_entries e
5 where t.component_itemid = e.componentid
6 and t.tree_id = e.part_tree_id
7 and t.component_id = 'A'
8 union all
9 select t.tree_id, t.component_id, t.component_itemid, t.id, e.part_tree_id, e.componentid, e.name, tv.lvl + 1, tv.tree_path || '=>' || e.name, tv.root_id
10 from tree_items t,
11 tree_entries e,
12 tree_view tv
13 where to_char(tv.component_itemid) = to_char(t.component_id)
14 and to_char(e.componentid) = to_char(t.component_itemid)
15 and tv.tree_id = t.tree_id
16 ) -- end of hierarchy view
17 search depth first by lvl set order1
18 select tree_path,
19 name,
20 componentid,
21 regexp_substr(tree_path, '[[:alpha:]]+', 1, 1) lvl1_part,
22 regexp_substr(tree_path, '[[:alpha:]]+', 1, 2) lvl2_part,
23 regexp_substr(tree_path, '[[:alpha:]]+', 1, 3) lvl3_part -- add more if there are further levels down the tree
24 from (
25 select tree_id, component_id, component_itemid, id, part_tree_id, componentid, name, lvl, tree_path, root_id, order1,
26 case when lvl - lead(lvl) over (order by order1) < 0 then 0 else 1 end is_leaf
27 from tree_view
28 )
29 where is_leaf = 1;
TREE_PATH NAME COMPONENTID LVL1_PART LVL2_PART LVL3_PART
---------------------------------------- ------------ ----------- -------------------- -------------------- --------------------
CLOCK=>BEZEL=>MATERIAL MATERIAL 117 CLOCK BEZEL MATERIAL
CLOCK=>BEZEL=>TEXTURE TEXTURE 118 CLOCK BEZEL TEXTURE
CLOCK=>FACE=>SHAPE SHAPE 119 CLOCK FACE SHAPE
CLOCK=>FACE=>DESIGN DESIGN 120 CLOCK FACE DESIGN
WATCH=>BAND=>MATERIAL MATERIAL 113 WATCH BAND MATERIAL
WATCH=>BAND=>COLOR COLOR 114 WATCH BAND COLOR
WATCH=>CASE=>MATERIAL MATERIAL 115 WATCH CASE MATERIAL
WATCH=>CASE=>SHAPE SHAPE 116 WATCH CASE SHAPE
RELOJ=>BISEL=>MATERIAL MATERIAL 125 RELOJ BISEL MATERIAL
RELOJ=>BISEL=>TEXTURA TEXTURA 126 RELOJ BISEL TEXTURA
RELOJ=>CARATULA=>FORMA FORMA 127 RELOJ CARATULA FORMA
RELOJ=>CARATULA=>DISEÑO DISEÑO 128 RELOJ CARATULA DISEÑO
RELOJPULSERA=>CORREA=>COLOR COLOR 122 RELOJPULSERA CORREA COLOR
RELOJPULSERA=>CORREA=>FORMA FORMA 127 RELOJPULSERA CORREA FORMA
RELOJPULSERA=>CAJA=>MATERIAL MATERIAL 123 RELOJPULSERA CAJA MATERIAL
RELOJPULSERA=>CAJA=>FORMA FORMA 124 RELOJPULSERA CAJA FORMA
16 rows selected
SQL>