从具有 Oracle 级别的 children id 获取 GrandParent 和 Parent 信息
Get GrandParent and Parent info from the children id with level in Oracle
我想从查询中的 Children ID 中检索 Grand Parent(TOP Level)和 Parent 的信息(ID 和 CODE),感谢ORACLE 功能“CONNECT BY”。最好的办法是检索完整的历史数据(所有祖先和 children 在同一个查询中)。
这里是数据:
ID | CODE | PARENT_ID
5953 | COMPANY |
230928 | D | 5953
7246 | C | 230928
243928 | C.5 | 7246
240961 | C.3 | 7246
7287 | C.4 | 7246
7286 | C.2 | 7246
7285 | C.1 | 7246
这是我想要的结果:
CHILDREN_ID | CHILDREN_CODE | PARENT_ID | PARENT_CODE | GRANDPARENT_CODE
5953 | COMPANY | | |
230928 | D | 5953 | COMPANY |
7246 | C | 230928 | D | COMPANY
243928 | C.5 | 7246 | C | D
240961 | C.3 | 7246 | C | D
7287 | C.4 | 7246 | C | D
7286 | C.2 | 7246 | C | D
7285 | C.1 | 7246 | C | D
我创建了这个查询:
SELECT ID AS "CHILDREN_ID", CODE AS "CHILDREN_CODE", PARENT_ID , PARENT_CODE, CONNECT_BY_ROOT CODE "GRANT_PARENT_CODE"
FROM PERSONS
WHERE LEVEL > 1
CONNECT BY PRIOR ID = PARENT_ID
但我没有检索到 Grand parent 的正确信息。
你能帮我吗?
我想我做到了!查询本身看起来很可怕,但我会解释:
select p.id children_id,
p.code children_code,
p.parent_id,
prior p.code parent_code,
case when level = 2 then null
when level = 3 then
connect_by_root code
else
substr(sys_connect_by_path(code, '\'),
instr(sys_connect_by_path(code, '\'), '\', 1, 2)+1,
(instr(sys_connect_by_path(code, '\'), '\', 1, 3)) - (instr(sys_connect_by_path(code, '\'), '\', 1, 2)+1))
end grandparent_code,
case when level = 2 then null
when level = 3 then connect_by_root to_char(id)
else substr(sys_connect_by_path(id, '\'),
instr(sys_connect_by_path(id, '\'), '\', 1, 2)+1,
(instr(sys_connect_by_path(id, '\'), '\', 1, 3)) - (instr(sys_connect_by_path(id, '\'), '\', 1, 2)+1))
end grandparent_id
from persons p
connect by prior p.id = p.parent_id
start with p.parent_id is null;
我确实使用了 connect_by_path 来显示从根目录到 child 条目的路径。详情见doc。
它将提供类似“..\grand-grand-parent\grand-parent\parent\child”的路径,因此只需替换掉 grand parent 即可。例外情况是 level = 2(无 grand-parent)和 level3 足以显示根。
希望对您有所帮助。不管怎样,我对一个有趣的问题 +1
这可以使用递归子查询分解子句相对简单地完成:
WITH rsqfc ( children_id, children_code, parent_id, parent_code, grandparent_id, grandparent_code ) AS (
SELECT id,
code,
NULL,
NULL,
NULL,
NULL
FROM persons
WHERE parent_id IS NULL
UNION ALL
SELECT p.id,
p.code,
r.children_id,
r.children_code,
r.parent_id,
r.parent_code
FROM rsqfc r
INNER JOIN persons p
ON ( r.children_id = p.parent_id )
)
SELECT *
FROM rsqfc
其中,对于示例数据:
CREATE TABLE persons(id, code, parent_id) AS
SELECT 5953, 'COMPANY', NULL FROM DUAL UNION ALL
SELECT 230928, 'D', 5953 FROM DUAL UNION ALL
SELECT 7246, 'C', 230928 FROM DUAL UNION ALL
SELECT 243928, 'C.5', 7246 FROM DUAL UNION ALL
SELECT 240961, 'C.3', 7246 FROM DUAL UNION ALL
SELECT 7287, 'C.4', 7246 FROM DUAL UNION ALL
SELECT 7286, 'C.2', 7246 FROM DUAL UNION ALL
SELECT 7285, 'C.1', 7246 FROM DUAL;
输出:
CHILDREN_ID | CHILDREN_CODE | PARENT_ID | PARENT_CODE | GRANDPARENT_ID | GRANDPARENT_CODE
----------: | :------------ | --------: | :---------- | -------------: | :---------------
5953 | COMPANY | null | null | null | null
230928 | D | 5953 | COMPANY | null | null
7246 | C | 230928 | D | 5953 | COMPANY
243928 | C.5 | 7246 | C | 230928 | D
240961 | C.3 | 7246 | C | 230928 | D
7287 | C.4 | 7246 | C | 230928 | D
7286 | C.2 | 7246 | C | 230928 | D
7285 | C.1 | 7246 | C | 230928 | D
db<>fiddle here
计算层次结构中某些中间节点的属性的最简单方法是使用递归 with
,您可以控制每一步的计算。但是对于这种特殊情况,您只需要父级的属性,因此您可以对连接的第一个结果进行分层查询:
with persons(id, code, parent_id) as (
select 5953, 'COMPANY', null from dual union all
select 230928, 'D', 5953 from dual union all
select 7246, 'C', 230928 from dual union all
select 243928, 'C.5', 7246 from dual union all
select 240961, 'C.3', 7246 from dual union all
select 7287, 'C.4', 7246 from dual union all
select 7286, 'C.2', 7246 from dual union all
select 7285, 'C.1', 7246 from dual
)
select
p.id children_id,
p.code children_code,
p.parent_id,
pp.code parent_code,
prior pp.code as grandparent_code
from persons p
left join persons pp
on p.parent_id = pp.id
start with p.parent_id is null
connect by prior p.id = p.parent_id
CHILDREN_ID | CHILDREN_CODE | PARENT_ID | PARENT_CODE | GRANDPARENT_CODE
----------: | :------------ | --------: | :---------- | :---------------
5953 | COMPANY | null | null | null
230928 | D | 5953 | COMPANY | null
7246 | C | 230928 | D | COMPANY
7285 | C.1 | 7246 | C | D
7286 | C.2 | 7246 | C | D
7287 | C.4 | 7246 | C | D
240961 | C.3 | 7246 | C | D
243928 | C.5 | 7246 | C | D
db<>fiddle here
我想从查询中的 Children ID 中检索 Grand Parent(TOP Level)和 Parent 的信息(ID 和 CODE),感谢ORACLE 功能“CONNECT BY”。最好的办法是检索完整的历史数据(所有祖先和 children 在同一个查询中)。
这里是数据:
ID | CODE | PARENT_ID
5953 | COMPANY |
230928 | D | 5953
7246 | C | 230928
243928 | C.5 | 7246
240961 | C.3 | 7246
7287 | C.4 | 7246
7286 | C.2 | 7246
7285 | C.1 | 7246
这是我想要的结果:
CHILDREN_ID | CHILDREN_CODE | PARENT_ID | PARENT_CODE | GRANDPARENT_CODE
5953 | COMPANY | | |
230928 | D | 5953 | COMPANY |
7246 | C | 230928 | D | COMPANY
243928 | C.5 | 7246 | C | D
240961 | C.3 | 7246 | C | D
7287 | C.4 | 7246 | C | D
7286 | C.2 | 7246 | C | D
7285 | C.1 | 7246 | C | D
我创建了这个查询:
SELECT ID AS "CHILDREN_ID", CODE AS "CHILDREN_CODE", PARENT_ID , PARENT_CODE, CONNECT_BY_ROOT CODE "GRANT_PARENT_CODE"
FROM PERSONS
WHERE LEVEL > 1
CONNECT BY PRIOR ID = PARENT_ID
但我没有检索到 Grand parent 的正确信息。
你能帮我吗?
我想我做到了!查询本身看起来很可怕,但我会解释:
select p.id children_id,
p.code children_code,
p.parent_id,
prior p.code parent_code,
case when level = 2 then null
when level = 3 then
connect_by_root code
else
substr(sys_connect_by_path(code, '\'),
instr(sys_connect_by_path(code, '\'), '\', 1, 2)+1,
(instr(sys_connect_by_path(code, '\'), '\', 1, 3)) - (instr(sys_connect_by_path(code, '\'), '\', 1, 2)+1))
end grandparent_code,
case when level = 2 then null
when level = 3 then connect_by_root to_char(id)
else substr(sys_connect_by_path(id, '\'),
instr(sys_connect_by_path(id, '\'), '\', 1, 2)+1,
(instr(sys_connect_by_path(id, '\'), '\', 1, 3)) - (instr(sys_connect_by_path(id, '\'), '\', 1, 2)+1))
end grandparent_id
from persons p
connect by prior p.id = p.parent_id
start with p.parent_id is null;
我确实使用了 connect_by_path 来显示从根目录到 child 条目的路径。详情见doc。
它将提供类似“..\grand-grand-parent\grand-parent\parent\child”的路径,因此只需替换掉 grand parent 即可。例外情况是 level = 2(无 grand-parent)和 level3 足以显示根。
希望对您有所帮助。不管怎样,我对一个有趣的问题 +1
这可以使用递归子查询分解子句相对简单地完成:
WITH rsqfc ( children_id, children_code, parent_id, parent_code, grandparent_id, grandparent_code ) AS (
SELECT id,
code,
NULL,
NULL,
NULL,
NULL
FROM persons
WHERE parent_id IS NULL
UNION ALL
SELECT p.id,
p.code,
r.children_id,
r.children_code,
r.parent_id,
r.parent_code
FROM rsqfc r
INNER JOIN persons p
ON ( r.children_id = p.parent_id )
)
SELECT *
FROM rsqfc
其中,对于示例数据:
CREATE TABLE persons(id, code, parent_id) AS
SELECT 5953, 'COMPANY', NULL FROM DUAL UNION ALL
SELECT 230928, 'D', 5953 FROM DUAL UNION ALL
SELECT 7246, 'C', 230928 FROM DUAL UNION ALL
SELECT 243928, 'C.5', 7246 FROM DUAL UNION ALL
SELECT 240961, 'C.3', 7246 FROM DUAL UNION ALL
SELECT 7287, 'C.4', 7246 FROM DUAL UNION ALL
SELECT 7286, 'C.2', 7246 FROM DUAL UNION ALL
SELECT 7285, 'C.1', 7246 FROM DUAL;
输出:
CHILDREN_ID | CHILDREN_CODE | PARENT_ID | PARENT_CODE | GRANDPARENT_ID | GRANDPARENT_CODE ----------: | :------------ | --------: | :---------- | -------------: | :--------------- 5953 | COMPANY | null | null | null | null 230928 | D | 5953 | COMPANY | null | null 7246 | C | 230928 | D | 5953 | COMPANY 243928 | C.5 | 7246 | C | 230928 | D 240961 | C.3 | 7246 | C | 230928 | D 7287 | C.4 | 7246 | C | 230928 | D 7286 | C.2 | 7246 | C | 230928 | D 7285 | C.1 | 7246 | C | 230928 | D
db<>fiddle here
计算层次结构中某些中间节点的属性的最简单方法是使用递归 with
,您可以控制每一步的计算。但是对于这种特殊情况,您只需要父级的属性,因此您可以对连接的第一个结果进行分层查询:
with persons(id, code, parent_id) as ( select 5953, 'COMPANY', null from dual union all select 230928, 'D', 5953 from dual union all select 7246, 'C', 230928 from dual union all select 243928, 'C.5', 7246 from dual union all select 240961, 'C.3', 7246 from dual union all select 7287, 'C.4', 7246 from dual union all select 7286, 'C.2', 7246 from dual union all select 7285, 'C.1', 7246 from dual ) select p.id children_id, p.code children_code, p.parent_id, pp.code parent_code, prior pp.code as grandparent_code from persons p left join persons pp on p.parent_id = pp.id start with p.parent_id is null connect by prior p.id = p.parent_id
CHILDREN_ID | CHILDREN_CODE | PARENT_ID | PARENT_CODE | GRANDPARENT_CODE ----------: | :------------ | --------: | :---------- | :--------------- 5953 | COMPANY | null | null | null 230928 | D | 5953 | COMPANY | null 7246 | C | 230928 | D | COMPANY 7285 | C.1 | 7246 | C | D 7286 | C.2 | 7246 | C | D 7287 | C.4 | 7246 | C | D 240961 | C.3 | 7246 | C | D 243928 | C.5 | 7246 | C | D
db<>fiddle here