Oracle Sql。使用连接进行递归选择

时间:2016-02-15 08:12:34

标签: sql oracle

我有一个包含应用程序的表和包含消息的表。应用程序具有分层结构,例如每个应用程序都有父级。我有一张信息表。每条消息都有一个密钥和一个应用程序ID。我希望能够通过它的密钥选择消息。如果找到当前应用程序然后返回它,如果没有,则尝试使用父ID找到它。 应用表:

id | name | parentId
--------------------
1  |parent| NULL
2  |child | 1

消息表:

key                  | text           | app
-------------------------------------------------
overriden.system.msg | some text      | 1
parent.msg           | parent txt     | 1
overriden.system.msg | overriden text | 2

因此,如果我在关键 overriden.system.msg 的子app(2)中,我想要覆盖文本。在密钥 parent.msg 上,我想获得 parent txt 。我知道它必须用cte来完成,但是我对sql的解释很少,cte对我来说是令人兴奋的。你能否提供这种情况的工作查询?或者您可以更好地了解如何在没有递归的情况下实现此类功能?

2 个答案:

答案 0 :(得分:1)

上述应该可以正常工作:

with app_tree (id, app, lvl) as
 ( select id , parentID , 0
    from  Apps 
    where id = 2
   union all
    select t.app, a.parentID, t.lvl + 1 from 
     Apps a 
     join app_tree t
     on t.app = a.id  ),
  all_msg as (
  select key, text, 
     row_number() over ( partition by key  order by lvl) overrideLevel
      from app_tree a
  join msg m
   on m.app = a.id )
  select  * from all_msg where
     overrideLevel =1

它返回:

    KEY                     TEXT
  -------------------------------------
    overriden.system.msg    overriden text  
    parent.msg              parent txt

首先,它使用parentid的递归查询获取指定id的所有应用程序的列表。之后,它会获得所有应用程序的所有函数列表,并根据级别为相同的键生成不断增加的数字。最后,它只取第一个可能的级别并忽略同一个键的所有父级别。

答案 1 :(得分:1)

它会帮助你:

with app (id, name, parent_id) as 
      (select 1, 'parent', null from dual union all
       select 2, 'child', 1 from dual)
    ,msg (key, text, app) as 
      (select 'overriden.system.msg', 'some text', 1 from dual union all
       select 'parent.msg', 'parent txt', 1 from dual union all
       select 'overriden.system.msg', 'overriden text', 2 from dual)

select key
      ,max(text) keep (dense_rank last order by nvl2(text,level,0)) msg
from
 (select *
  from app a
  join msg m on (a.id = m.app)) v
start with v.parent_id is null
connect by prior v.id = v.parent_id and prior v.key = v.key
group by key