在分层查询中用父数据覆盖空值
Overwriting nulls with parent data in a hierarchical query
我有一个 table,格式如下:
pk fk parent
===== ====== ========
001 23 000
002 null 001
003 46 001
004 12 000
005 null 004
006 null 005
=====================
pk
是每一行的主键,fk
是另一个的外键table我稍后需要加入,parent
是记录的分层父级。我可以使用
对此数据创建分层查询
select
lpad(' ',2*level)||pk "primary_key",
fk "foreign_key",
sys_connect_by_path(pk,'/') "path"
from example_table
connect by prior pk = parent
;
我的问题是如何用没有空值的最低祖先的外键覆盖行的 null
外键?我在这种情况下的预期输出是
pk fk parent
========= ==== ======
001 23 000
002 23 001
003 46 001
004 12 000
005 12 004
006 12 005
====================
(填充主键以显示层次结构。)
您可以使用标准递归通用 table 表达式来表达:
with cte (pk, fk, parent, lvl, pat) as (
select to_char(pk), fk, parent, 0, to_char(pk) from mytable where parent = 0
union all
select lpad(' ', 2 * (lvl + 1)) || t.pk, coalesce(t.fk, c.fk), t.parent, c.lvl + 1, c.pat || '/' || t.pk
from cte c
inner join mytable t on t.parent = c.pk
)
select pk, fk, parent from cte order by pat
PK | FK | PARENT
:---- | -: | -----:
1 | 23 | 0
2 | 23 | 1
3 | 46 | 1
4 | 12 | 0
5 | 12 | 4
6 | 12 | 5
只需使用 sys_connect_by_path(fk,'/')
聚合父 FK 并使用正则表达式取最后一个:
with example_table( pk, fk, parent) as (
select '001', 23 , '000' from dual union all
select '002', null, '001' from dual union all
select '003', 46 , '001' from dual union all
select '004', 12 , '000' from dual union all
select '005', null, '004' from dual union all
select '006', null, '005' from dual
)
select
lpad(' ',2*level)||pk "primary_key",
fk "foreign_key",
nvl(fk, regexp_substr(sys_connect_by_path(fk,'/'),'(\d+)/*$',1,1,'',1)) fk2,
sys_connect_by_path(pk,'/') "path"
from example_table
connect by prior pk = parent
;
结果:
primary_key foreign_key FK2 path
------------ ----------- ---------- --------------------------------------------------------------------------------
001 23 23 /001
002 23 /001/002
003 46 46 /001/003
004 12 12 /004
005 12 /004/005
006 12 /004/005/006
002 /002
003 46 46 /003
005 /005
006 /005/006
006 /006
11 rows selected.
我有一个 table,格式如下:
pk fk parent
===== ====== ========
001 23 000
002 null 001
003 46 001
004 12 000
005 null 004
006 null 005
=====================
pk
是每一行的主键,fk
是另一个的外键table我稍后需要加入,parent
是记录的分层父级。我可以使用
select
lpad(' ',2*level)||pk "primary_key",
fk "foreign_key",
sys_connect_by_path(pk,'/') "path"
from example_table
connect by prior pk = parent
;
我的问题是如何用没有空值的最低祖先的外键覆盖行的 null
外键?我在这种情况下的预期输出是
pk fk parent
========= ==== ======
001 23 000
002 23 001
003 46 001
004 12 000
005 12 004
006 12 005
====================
(填充主键以显示层次结构。)
您可以使用标准递归通用 table 表达式来表达:
with cte (pk, fk, parent, lvl, pat) as (
select to_char(pk), fk, parent, 0, to_char(pk) from mytable where parent = 0
union all
select lpad(' ', 2 * (lvl + 1)) || t.pk, coalesce(t.fk, c.fk), t.parent, c.lvl + 1, c.pat || '/' || t.pk
from cte c
inner join mytable t on t.parent = c.pk
)
select pk, fk, parent from cte order by pat
PK | FK | PARENT :---- | -: | -----: 1 | 23 | 0 2 | 23 | 1 3 | 46 | 1 4 | 12 | 0 5 | 12 | 4 6 | 12 | 5
只需使用 sys_connect_by_path(fk,'/')
聚合父 FK 并使用正则表达式取最后一个:
with example_table( pk, fk, parent) as (
select '001', 23 , '000' from dual union all
select '002', null, '001' from dual union all
select '003', 46 , '001' from dual union all
select '004', 12 , '000' from dual union all
select '005', null, '004' from dual union all
select '006', null, '005' from dual
)
select
lpad(' ',2*level)||pk "primary_key",
fk "foreign_key",
nvl(fk, regexp_substr(sys_connect_by_path(fk,'/'),'(\d+)/*$',1,1,'',1)) fk2,
sys_connect_by_path(pk,'/') "path"
from example_table
connect by prior pk = parent
;
结果:
primary_key foreign_key FK2 path
------------ ----------- ---------- --------------------------------------------------------------------------------
001 23 23 /001
002 23 /001/002
003 46 46 /001/003
004 12 12 /004
005 12 /004/005
006 12 /004/005/006
002 /002
003 46 46 /003
005 /005
006 /005/006
006 /006
11 rows selected.