具有层次结构的 Oracle 复杂查询

时间:2021-02-09 14:11:58

标签: sql oracle

以下是我的示例数据1

CP | NP |MC |DS |NNP
--- ---- --- -- ---
A  |  B |   |   |C
C  |  D | XX|YY |E
E  |  F | ZZ|11 |

预期输出 1

NP |MC |DS 
--- ---- --- 
 B | ZZ|11

这里的“CP”和“NNP”列是分层的(即) 我们将从如下查询开始,针对特定的 NP,然后使用以下逻辑获取相应的 MC 和 DS 值

select MC, DS from tabl1
where NP=B
  1. 首先查看列 CP 中的值 A,然后查看是否 列NNP作为对应值,这里是列NNP中的C值
  2. 如果有对应的值表单列 CP 存在于 NNP 中,然后查看 CP 列的 C 值,然后查看 如果 NNP 作为这里的对应值,则它是 NNP 列中的 E 值(重复这些步骤,直到我们做到 在 NNP 列中找不到与列 CP 对应的条目)
  3. 为列 MC 和 DS 获取 E 值对应的值

以下是我的示例数据2

CP | NP |MC |DS |NNP
--- ---- --- -- ---
A  |  B | 96|KK |C
C  |  D | XX|YY |E
E  |  F | ZZ|11 |

预期输出2(如果对应的根值不为空,那么我们也需要获取这些值

NP |MC |DS 
--- ---- --- 
 B | 96|KK
 B | ZZ|11

2 个答案:

答案 0 :(得分:1)

直接应用分层(connect by)查询:

select  connect_by_root(np) as np, mc, ds
from    sample_data
where   connect_by_isleaf = 1   -- OR:  nnp is null   (IF NEEDED, SEE BELOW)
start   with cp = 'A'
connect by cp = prior nnp
;

在您的输出中,在列 NP 中有值 B,它是“根”行(起始行)中的值。您可以在此处使用 connect_by_root。所有其他值都来自叶行(层次结构中的“最后”行)。这是我们需要使用过滤器 connect_by_isleaf = 1 的地方 - 非叶行(至少有一个子行)的值为 0,叶行的值为 1。

请注意,“叶子”意味着没有更多的孩子。如果 NNPnull 或它不是 null 但在 CP 列中找不到该值,都可能发生这种情况。如果您只需要 NNPnull 的叶行,您可以更改 where 子句,如上面的代码所示。

EDIT OP 请求修改 - 除了 leaf 之外,输出还应包括 root 行,但前提是mcds 值(或两者)是/不是 null。这可以通过更改 where 子句来实现,它应该是:

...
where (connect_by_isleaf = 1) 
   or (level = 1 and (mc is not null or ds is not null))
...

答案 1 :(得分:0)

您可以使用递归 CTE。例如:

with
n (cp, np, mc, ds, nnp, lvl) as (
  select cp, np, mc, ds, nnp, 1 from t where cp not in (
    select nnp from t where nnp is not null
  )
 union all
  select n.cp, n.np, n.mc, n.ds, t.nnp, n.lvl + 1
  from n
  join t on t.cp = n.nnp 
),
m as (select np, max(lvl) as max_lvl from n group by np)
select m.np, n.mc, n.ds
from n
join m on m.np = n.np and m.max_lvl = n.lvl

我没有测试这个查询的语法问题,但策略是正确的。

相关问题