如何在 Oracle SQL 中检索父行的所有递归子代?
Posted
技术标签:
【中文标题】如何在 Oracle SQL 中检索父行的所有递归子代?【英文标题】:How to retrieve all recursive children of parent row in Oracle SQL? 【发布时间】:2013-06-25 20:06:04 【问题描述】:我有一个递归查询,它确实扩展了这个 Java 猴子的 SQL 知识的极限。现在终于凌晨 1:30,可能是时候开始寻求帮助了。这是 Google 让我失望的少数几次之一。
表格如下:
Parent_ID CHILD_ID QTY
25 26 1
25 27 2
26 28 1
26 29 1
26 30 2
27 31 1
27 32 1
27 33 2
我正在尝试获得以下结果,其中父母将每个孩子都列在他们的下方。请注意,数量的级联也是如此。
BASE PARENT_ID CHILD_ID QTY
25 25 26 1
25 25 27 2
25 26 28 1
25 26 29 1
25 26 30 1
25 27 31 2
25 27 32 2
25 27 33 4
26 26 28 1
26 26 29 1
26 26 30 2
27 27 31 1
27 27 32 1
27 27 33 2
我尝试了以下几种偏差都无济于事。
SELECT *
FROM MD_BOMS
START WITH PARENT_ID is not null
CONNECT BY PRIOR CHILD_ID = PARENT_ID
ORDER BY PARENT_ID, CHILD_ID
我正在使用 Oracle 数据库。任何建议、想法等将不胜感激。这似乎很接近,但我不确定它是否是我正在寻找的:Retrieve all Children and their Children, recursive SQL
基于(Retrieve all Children and their Children, recursive SQL)我也尝试了以下方法,但收到“ WITH 子句中查询名称的非法引用”错误:
with cte as (
select CHILD_ID, PARENT_ID, CHILD_ID as head
from MD_BOMS
where PARENT_ID is not null
union all
select ch.CHILD_ID, ch.PARENT_ID, p.head
from MD_BOMS ch
join cte pa
on pa.CHILD_ID = ch.PARENT_ID
)
select *
from cte
【问题讨论】:
我不明白,数量必须如何计算。请解释一下。 嗨奥拉夫。这种特殊的结构对物料清单 (BOM) 进行建模。这是一种描述哪些组件构成其他组件的方式。不足之处在于分量 qtys 是乘法的。例如,如果 25 中有 2 个 27,那么 25 中就会有 4 个 31。回想起来,我在原来的帖子中确实打错了字。 25 中应该只有 1 30。 【参考方案1】:你很接近:
select connect_by_root parent_id base, parent_id, child_id, qty
from md_boms
connect by prior child_id = parent_id
order by base, parent_id, child_id;
BASE PARENT_ID CHILD_ID QTY
---------- ---------- ---------- ----------
25 25 26 1
25 25 27 2
25 26 28 1
25 26 29 1
25 26 30 2
25 27 31 1
25 27 32 1
25 27 33 2
26 26 28 1
26 26 29 1
26 26 30 2
27 27 31 1
27 27 32 1
27 27 33 2
14 rows selected
connect_by_root
operator 为您提供基础parent_id
。
SQL Fiddle.
我不确定您是如何计算您的 qty
的。我猜你想要通往孩子的道路的总数,但这与你所展示的不符。然后,作为起点,非常大量借鉴this answer,您可以尝试以下操作:
with hierarchy as (
select connect_by_root parent_id base, parent_id, child_id, qty,
sys_connect_by_path(child_id, '/') as path
from md_boms
connect by prior child_id = parent_id
)
select h.base, h.parent_id, h.child_id, sum(e.qty)
from hierarchy h
join hierarchy e on h.path like e.path ||'%'
group by h.base, h.parent_id, h.child_id
order by h.base, h.parent_id, h.child_id;
BASE PARENT_ID CHILD_ID SUM(E.QTY)
---------- ---------- ---------- ----------
25 25 26 1
25 25 27 2
25 26 28 2
25 26 29 2
25 26 30 3
25 27 31 3
25 27 32 3
25 27 33 4
26 26 28 1
26 26 29 1
26 26 30 2
27 27 31 1
27 27 32 1
27 27 33 2
14 rows selected
【讨论】:
亚历克斯,谢谢!当我接受 ThinkJet 的回答时,这就是我所寻找的一切。如果我可以投票给你,我会的。 同意@WillLovett :-)【参考方案2】:@AlexPoole 的答案很棒,我只是想用更直观的查询变体来扩展他的答案,以沿路径求和值。
此变体基于recursive subquery factoring 功能,在Oracle 11g R2
中引入。
with recursion_view(base, parent_id, child_id, qty) as (
-- first step, get rows to start with
select
parent_id base,
parent_id,
child_id,
qty
from
md_boms
union all
-- subsequent steps
select
-- retain base value from previous level
previous_level.base,
-- get information from current level
current_level.parent_id,
current_level.child_id,
-- accumulate sum
(previous_level.qty + current_level.qty) as qty
from
recursion_view previous_level,
md_boms current_level
where
current_level.parent_id = previous_level.child_id
)
select
base, parent_id, child_id, qty
from
recursion_view
order by
base, parent_id, child_id
SQLFiddle example(用一个数据行扩展以演示超过 2 个级别的工作)
【讨论】:
ThinkJet,这很好用!在我从 10g 升级到 11g R2 之后,我所要做的就是复制和粘贴,它就像一个魅力。我唯一改变的是用乘法代替加法,这给了我正确的数量。我对你和亚历克斯的回答都感到非常惊讶。这对我有很大帮助! 关于更多问题是否可以...当我尝试将您的查询转换为视图时,我收到 SQL Parse Exception: Error(s) parsing SQL: syntax error near ! 如下:with !*recursion_view(base, parent_id, child_id, qty) as ( *! 附近有语法错误: with recursion_view*!*(base, parent_id, child_id,数量)作为( @WillLovett - 错误中的!
和*
来自哪里?您可以通过在其前面粘贴create view my_view as
将其转换为视图,并且不更改任何其他内容。如果您正在做其他事情,您可能需要提出一个新问题,显示您在问题中使用的确切代码。
@AlexPoole 我发布了两张截图:williverstravels.com/JDev/Forums/***/17358109/… 和williverstravels.com/JDev/Forums/***/17358109/… 第一张带有 ! * 是当我使用 JDeveloper 11g 时,使用 Database Navigator,右键单击 View 并选择“New View”。单击“确定”时收到错误消息。我确实可以通过 sql 脚本创建视图,但是当我尝试查看数据时,我收到 ORA_00600 错误。
在花了 6 个小时之后,我决定不使用 JDev 的图形编辑器,而简单地写 SELECT * FROM BOMS_VIEW;它就像一个魅力。我只是不能使用数据选项卡在编辑器中查看记录。希望我在 5 小时前就知道了。以上是关于如何在 Oracle SQL 中检索父行的所有递归子代?的主要内容,如果未能解决你的问题,请参考以下文章