我一直在阅读Oracle中的CONNECT BY
和CTE,但我无法提出解决方案。我不知道如何正确使用CONNECT BY
来满足我的需求,而Oracle中的递归CTE仅限于2个分支(一个UNION ALL
)而我使用3个分支。
在SQL Server中,我发现这个article之后很容易。我只添加了另一个UNION ALL
关于返回所有节点引用。
我想做的是拥有这样的层次结构:
Code|Father
1 |NULL
2 |1
3 |2
这应该归还我:
Node|Father|Level|JumpsToFather
1 |1 |1 |0
2 |1 |2 |1
2 |2 |2 |0
3 |1 |3 |2
3 |2 |3 |1
3 |3 |3 |0
注意:是的我需要返回一个引用它自己计为层次结构上的零跳转
答案 0 :(得分:1)
这是使用递归CTE的解决方案。我使用lvl
作为列标题,因为level
是Oracle中的保留字。您还将看到术语中的其他差异。我使用“parent”表示更高级别,“祖先”表示> = 0步(以满足您将节点显示为其自己的祖先的要求)。我使用ORDER BY
子句使输出与你的输出相匹配;您可能需要也可能不需要订购的行。
您的问题促使我再次详细阅读有关分层查询的内容,以了解是否可以使用它们而不是递归CTE。实际上我已经知道你可以使用CONNECT_BY_PATH
,但是使用substr
只是为了检索分层路径中的顶级水平并不令人满意,必须有更好的方法。 (如果这是使用分层查询的唯一方法,我肯定会去递归CTE路线,如果它可用)。如果我能找到一个好的,我会在这里添加分层查询解决方案。
with h ( node, parent ) as (
select 1 , null from dual union all
select 2 , 1 from dual union all
select 3 , 2 from dual
),
r ( node , ancestor, steps ) as (
select node , node , 0
from h
union all
select r.node, h.parent, steps + 1
from h join r
on h.node = r.ancestor
)
select node, ancestor,
1+ (max(steps) over (partition by node)) as lvl, steps
from r
where ancestor is not null
order by lvl, steps desc;
NODE ANCESTOR LVL STEPS
---------- ---------- ---------- ----------
1 1 1 0
2 1 2 1
2 2 2 0
3 1 3 2
3 2 3 1
3 3 3 0
已添加:分层查询解决方案
好的 - 找到了。请测试两个解决方案,看看哪个表现更好;通过对不同设置的测试,递归CTE比分层查询快得多,但这可能取决于具体情况。另外:递归CTE仅适用于Oracle 11.2及更高版本;分层解决方案适用于旧版本。
我添加了一些测试数据以匹配Anatoliy。
with h ( node, parent ) as (
select 1 , null from dual union all
select 2 , 1 from dual union all
select 3 , 2 from dual union all
select 4 , 2 from dual union all
select 5 , 4 from dual
)
select node,
connect_by_root node as ancestor,
max(level) over (partition by node) as lvl,
level - 1 as steps
from h
connect by parent = prior node
order by node, ancestor;
NODE ANCESTOR LVL STEPS
---------- ---------- ---------- ----------
1 1 1 0
2 1 2 1
2 2 2 0
3 1 3 2
3 2 3 1
3 3 3 0
4 1 3 2
4 2 3 1
4 4 3 0
5 1 4 3
5 2 4 2
5 4 4 1
5 5 4 0
答案 1 :(得分:1)
resources(:waiting_lists) do
collection do
get(':role/get_role', action: :get_role)
end
end
正如你所看到的,我要添加一些数据来测试我的sql,这里是输出
with t as ( select code, parent, level l
from (select 1 as code, NULL as parent from dual union
select 2 , 1 from dual union
select 3 , 2 from dual
-- add some more data for demo case
union
select 4 , 2 from dual union
select 5 , 4 from dual
)
start with parent is null
connect by prior code = parent )
select code, (select code
from t t1
where l = ll
and rownum = 1
start with t1.code = main_t.code
connect by prior t1.parent = t1.code
) parent,
l code_level,
jumps
from (
select distinct t.*, l-level jumps, level ll
from t
connect by level <= l
) main_t
order by code, parent