获取Oracle

时间:2016-07-19 14:48:06

标签: oracle

我一直在阅读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

注意:是的我需要返回一个引用它自己计为层次结构上的零跳转

2 个答案:

答案 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)

问题是,我花了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