Oracle 中的分层 SQL
hierarchic SQL in Oracle
我有很多 table 列,所以为了简单起见,我只选择了相关的列。
有组件和模块。组件可以用作最终产品,但可以构建在另一个组件 = modul 中。模块也是如此。一个模块可以作为最终产品,也可以构建在另一个组件中 = modul.
在真实的 table 中只有数字,但为了更好地理解,我使用关系 component-modul
所以例如 componentA + componentB = modulAB 但 componentA 也可以用作最终项目。
因此在 table 中有 2 列标识组件是否正在使用,比如说作为工厂中的最终项目
assembly_id - 表示该项目是一个模块,因此必须有一些组件(孩子)
in_assembly_id - 意味着这个项目将被构建在另一个项目/模块中
如上所述,项目可以是最终的,在这种情况下,两列都有 -1,但同时该项目可以构建在另一个项目(模块)中,因此还有另一行包含列 in_assembly_id < > -1 .在我的示例中 componentA
这同样适用于已经是具有某些组件的模块并且可以是最终项目或将构建在另一个项目(模块)中的项目(在_assembly_id.
列中指示)
我的目标是为特定项目找到模块项目,该项目也可以作为最终产品并不重要
我可以使用 join,但只能找到上一级。
select distinct c.item, c.in_assembly_id, modul, modul_id from items c ,lateral (select a.item modul,a.assembly_id modul_id from items a where a.assembly_id=c.in_assembly_id)
where c.item = 'componentA' and c.in_assembly_id <> -1;
ITEM IN_ASSEMBLY_ID MODUL MODUL_ID
componentA 100 modulAC 100
componentA 50 modulAB 50
所以要查看整个结构,因为 modulAC 是内置在 modulACDE 中的,而且需要分层查询才能看到这样的输出
1.
ITEM IN_ASSEMBLY_ID assembly_id type/level
componentA -1 50 comp
modulAB 50 -1 modul
componentA -1 100 comp
modulAC 100 -1 modul
modulAC 100 500 modul
modulACDE 500 -1 modul
最高模数
ITEM IN_ASSEMBLY_ID assembly_id type/level
componentA -1 50 comp
modulAB 50 -1 modul
componentA -1 100 comp
modulACDE 500 -1 modul
我从 connect by 子句开始,但它对我不起作用,我不知道为什么我得到 modulDE
select distinct * from items
connect by nocycle in_assembly_id = prior assembly_id
start with item = 'componentA' and in_assembly_id <> '-1';
这是我的数据
create table items (
item_id number,
item varchar2(12),
assembly_id number,
in_assembly_id number
);
insert into items values ( 1 , 'componentA' , -1 , -1 );
insert into items values ( 2 , 'componentA' , -1 , 50 );
insert into items values ( 3 , 'componentB' , -1 , 50 );
insert into items values ( 4 , 'modulAB' , 50 , -1 );
insert into items values ( 5 , 'componentA' , -1 , 100 );
insert into items values ( 6 , 'componentC' , -1 , 100);
insert into items values ( 7 , 'modulAC' , 100 , -1 );
insert into items values ( 7 , 'modulAC' , 100 , 500 );
insert into items values ( 8 , 'componentD' , -1 , 200 );
insert into items values ( 9 , 'componentE' , -1 , 200 );
insert into items values ( 10 , 'modulDE' , 200 , 500 );
insert into items values ( 11 , 'modulACDE' , 500 , -1 );
insert into items values ( 12 , 'componentF' , -1 , -1 );
insert into items values ( 13 , 'componentG' , -1 , -1 );
my goal is to find for particular item the modul
item , doesn't matter that the item can be as final product as well
这将获得 componentA
的所有 modul
:
SELECT CONNECT_BY_ROOT( item_id ) AS root_item_id,
CONNECT_BY_ROOT( item ) AS root_item,
item_id,
item,
assembly_id,
SYS_CONNECT_BY_PATH( item_id, ',' ) AS path_item_id,
SYS_CONNECT_BY_PATH( item, ',' ) AS path_item
FROM items
WHERE assembly_id <> -1
START WITH
item = 'componentA'
AND ( assembly_id, in_assembly_id ) NOT IN ((-1,-1))
CONNECT BY NOCYCLE
PRIOR in_assembly_id = assembly_id
ORDER SIBLINGS BY item, item_id;
输出:
ROOT_ITEM_ID | ROOT_ITEM | ITEM_ID | ITEM | ASSEMBLY_ID | PATH_ITEM_ID | PATH_ITEM
-----------: | :--------- | ------: | :-------- | ----------: | :----------- | :-------------------------------------
2 | componentA | 4 | modulAB | 50 | ,2,4 | ,componentA,modulAB
2 | componentA | 7 | modulAC | 100 | ,2,4,5,7 | ,componentA,modulAB,componentA,modulAC
2 | componentA | 7 | modulAC | 100 | ,2,4,6,7 | ,componentA,modulAB,componentC,modulAC
2 | componentA | 10 | modulDE | 200 | ,2,4,8,10 | ,componentA,modulAB,componentD,modulDE
2 | componentA | 10 | modulDE | 200 | ,2,4,9,10 | ,componentA,modulAB,componentE,modulDE
5 | componentA | 7 | modulAC | 100 | ,5,7 | ,componentA,modulAC
5 | componentA | 10 | modulDE | 200 | ,5,7,8,10 | ,componentA,modulAC,componentD,modulDE
5 | componentA | 10 | modulDE | 200 | ,5,7,9,10 | ,componentA,modulAC,componentE,modulDE
5 | componentA | 7 | modulAC | 100 | ,5,7 | ,componentA,modulAC
5 | componentA | 11 | modulACDE | 500 | ,5,7,11 | ,componentA,modulAC,modulACDE
db<>fiddle here
更新
SELECT CONNECT_BY_ROOT( item_id ) AS root_item_id,
CONNECT_BY_ROOT( item ) AS root_item,
item_id,
item,
assembly_id,
SYS_CONNECT_BY_PATH( item_id, ',' ) AS path_item_id,
SYS_CONNECT_BY_PATH( item, ',' ) AS path_item
FROM items
WHERE assembly_id > -1
START WITH
item = 'componentA'
AND ( assembly_id, in_assembly_id ) NOT IN ((-1,-1))
CONNECT BY NOCYCLE
PRIOR in_assembly_id = assembly_id
AND assembly_id > -1
ORDER SIBLINGS BY item, item_id;
输出:
ROOT_ITEM_ID | ROOT_ITEM | ITEM_ID | ITEM | ASSEMBLY_ID | PATH_ITEM_ID | PATH_ITEM
-----------: | :--------- | ------: | :-------- | ----------: | :----------- | :----------------------------
2 | componentA | 4 | modulAB | 50 | ,2,4 | ,componentA,modulAB
5 | componentA | 7 | modulAC | 100 | ,5,7 | ,componentA,modulAC
5 | componentA | 7 | modulAC | 100 | ,5,7 | ,componentA,modulAC
5 | componentA | 11 | modulACDE | 500 | ,5,7,11 | ,componentA,modulAC,modulACDE
db<>fiddle here
我有很多 table 列,所以为了简单起见,我只选择了相关的列。
有组件和模块。组件可以用作最终产品,但可以构建在另一个组件 = modul 中。模块也是如此。一个模块可以作为最终产品,也可以构建在另一个组件中 = modul.
在真实的 table 中只有数字,但为了更好地理解,我使用关系 component-modul 所以例如 componentA + componentB = modulAB 但 componentA 也可以用作最终项目。 因此在 table 中有 2 列标识组件是否正在使用,比如说作为工厂中的最终项目 assembly_id - 表示该项目是一个模块,因此必须有一些组件(孩子) in_assembly_id - 意味着这个项目将被构建在另一个项目/模块中
如上所述,项目可以是最终的,在这种情况下,两列都有 -1,但同时该项目可以构建在另一个项目(模块)中,因此还有另一行包含列 in_assembly_id < > -1 .在我的示例中 componentA
这同样适用于已经是具有某些组件的模块并且可以是最终项目或将构建在另一个项目(模块)中的项目(在_assembly_id.
列中指示)我的目标是为特定项目找到模块项目,该项目也可以作为最终产品并不重要
我可以使用 join,但只能找到上一级。
select distinct c.item, c.in_assembly_id, modul, modul_id from items c ,lateral (select a.item modul,a.assembly_id modul_id from items a where a.assembly_id=c.in_assembly_id)
where c.item = 'componentA' and c.in_assembly_id <> -1;
ITEM IN_ASSEMBLY_ID MODUL MODUL_ID
componentA 100 modulAC 100
componentA 50 modulAB 50
所以要查看整个结构,因为 modulAC 是内置在 modulACDE 中的,而且需要分层查询才能看到这样的输出 1.
ITEM IN_ASSEMBLY_ID assembly_id type/level
componentA -1 50 comp
modulAB 50 -1 modul
componentA -1 100 comp
modulAC 100 -1 modul
modulAC 100 500 modul
modulACDE 500 -1 modul
最高模数
ITEM IN_ASSEMBLY_ID assembly_id type/level
componentA -1 50 comp
modulAB 50 -1 modul
componentA -1 100 comp
modulACDE 500 -1 modul
我从 connect by 子句开始,但它对我不起作用,我不知道为什么我得到 modulDE
select distinct * from items
connect by nocycle in_assembly_id = prior assembly_id
start with item = 'componentA' and in_assembly_id <> '-1';
这是我的数据
create table items (
item_id number,
item varchar2(12),
assembly_id number,
in_assembly_id number
);
insert into items values ( 1 , 'componentA' , -1 , -1 );
insert into items values ( 2 , 'componentA' , -1 , 50 );
insert into items values ( 3 , 'componentB' , -1 , 50 );
insert into items values ( 4 , 'modulAB' , 50 , -1 );
insert into items values ( 5 , 'componentA' , -1 , 100 );
insert into items values ( 6 , 'componentC' , -1 , 100);
insert into items values ( 7 , 'modulAC' , 100 , -1 );
insert into items values ( 7 , 'modulAC' , 100 , 500 );
insert into items values ( 8 , 'componentD' , -1 , 200 );
insert into items values ( 9 , 'componentE' , -1 , 200 );
insert into items values ( 10 , 'modulDE' , 200 , 500 );
insert into items values ( 11 , 'modulACDE' , 500 , -1 );
insert into items values ( 12 , 'componentF' , -1 , -1 );
insert into items values ( 13 , 'componentG' , -1 , -1 );
my goal is to find for particular item the
modul
item , doesn't matter that the item can be as final product as well
这将获得 componentA
的所有 modul
:
SELECT CONNECT_BY_ROOT( item_id ) AS root_item_id,
CONNECT_BY_ROOT( item ) AS root_item,
item_id,
item,
assembly_id,
SYS_CONNECT_BY_PATH( item_id, ',' ) AS path_item_id,
SYS_CONNECT_BY_PATH( item, ',' ) AS path_item
FROM items
WHERE assembly_id <> -1
START WITH
item = 'componentA'
AND ( assembly_id, in_assembly_id ) NOT IN ((-1,-1))
CONNECT BY NOCYCLE
PRIOR in_assembly_id = assembly_id
ORDER SIBLINGS BY item, item_id;
输出:
ROOT_ITEM_ID | ROOT_ITEM | ITEM_ID | ITEM | ASSEMBLY_ID | PATH_ITEM_ID | PATH_ITEM -----------: | :--------- | ------: | :-------- | ----------: | :----------- | :------------------------------------- 2 | componentA | 4 | modulAB | 50 | ,2,4 | ,componentA,modulAB 2 | componentA | 7 | modulAC | 100 | ,2,4,5,7 | ,componentA,modulAB,componentA,modulAC 2 | componentA | 7 | modulAC | 100 | ,2,4,6,7 | ,componentA,modulAB,componentC,modulAC 2 | componentA | 10 | modulDE | 200 | ,2,4,8,10 | ,componentA,modulAB,componentD,modulDE 2 | componentA | 10 | modulDE | 200 | ,2,4,9,10 | ,componentA,modulAB,componentE,modulDE 5 | componentA | 7 | modulAC | 100 | ,5,7 | ,componentA,modulAC 5 | componentA | 10 | modulDE | 200 | ,5,7,8,10 | ,componentA,modulAC,componentD,modulDE 5 | componentA | 10 | modulDE | 200 | ,5,7,9,10 | ,componentA,modulAC,componentE,modulDE 5 | componentA | 7 | modulAC | 100 | ,5,7 | ,componentA,modulAC 5 | componentA | 11 | modulACDE | 500 | ,5,7,11 | ,componentA,modulAC,modulACDE
db<>fiddle here
更新
SELECT CONNECT_BY_ROOT( item_id ) AS root_item_id,
CONNECT_BY_ROOT( item ) AS root_item,
item_id,
item,
assembly_id,
SYS_CONNECT_BY_PATH( item_id, ',' ) AS path_item_id,
SYS_CONNECT_BY_PATH( item, ',' ) AS path_item
FROM items
WHERE assembly_id > -1
START WITH
item = 'componentA'
AND ( assembly_id, in_assembly_id ) NOT IN ((-1,-1))
CONNECT BY NOCYCLE
PRIOR in_assembly_id = assembly_id
AND assembly_id > -1
ORDER SIBLINGS BY item, item_id;
输出:
ROOT_ITEM_ID | ROOT_ITEM | ITEM_ID | ITEM | ASSEMBLY_ID | PATH_ITEM_ID | PATH_ITEM -----------: | :--------- | ------: | :-------- | ----------: | :----------- | :---------------------------- 2 | componentA | 4 | modulAB | 50 | ,2,4 | ,componentA,modulAB 5 | componentA | 7 | modulAC | 100 | ,5,7 | ,componentA,modulAC 5 | componentA | 7 | modulAC | 100 | ,5,7 | ,componentA,modulAC 5 | componentA | 11 | modulACDE | 500 | ,5,7,11 | ,componentA,modulAC,modulACDE
db<>fiddle here