在 Oracle CONNECT BY 分层查询中引用父列

Xop*_*ter 2 sql oracle connect-by hierarchical-data

我有看起来像这样的数据:

KEY1   KEY2      KEY3   LKEY1  LKEY2     LKEY3  FLAG
====== ========= ====== ====== ========= ====== =====
09/10  10000     A1234  09/10  AU000123  A1234  1
09/10  10000     A1234  09/10  AU000456  A1234  1
09/10  10000     A1234  09/10  AX000001  A1234  1
09/10  AX000001  A1234  09/10  AE000010  A1234  0
09/10  AX000001  A1234  09/10  AE000020  A1234  0
09/10  AX000001  A1234  09/10  AE000030  A1234  0
09/10  10000     A1234  09/10  AX000002  A1234  0
09/10  AX000002  A1234  09/10  AE000040  A1234  0
09/10  10000     A1234  09/10  AU000789  A1234  0
Run Code Online (Sandbox Code Playgroud)

这是分层数据,我将查询根复合键(在本例中09/10 10000 A1234);该FLAG字段是指由LKEYx键标识的“对象” 。可以有任意数量的嵌套级别。(请注意,KEY1KEY3字段不必是不变的,如上面的示例所示,只要保留层次结构即可。)

我想要检索的是叶节点,如果叶的父节点与第二个字符的KEY2长度相同LKEY2或包含一个X作为第二个字符,则返回直接父节点。在这种情况下,我们还需要将记录标记为可选......所以,像这样:

KEY1   KEY2      KEY3   OPTION  FLAG
====== ========= ====== ======= =====
09/10  AU000123  A1234  0       1
09/10  AU000456  A1234  0       1
09/10  AX000001  A1234  1       1
09/10  AX000002  A1234  1       0
09/10  AU000789  A1234  0       0
Run Code Online (Sandbox Code Playgroud)

我写了一个查询来做到这一点,但它并不漂亮。此外,为了区分可选记录,它假设所有叶节点都在树下的同一级别;然而,这不一定是真的。我的查询如下:

with queryKeys as (
  select '09/10' key1,
         '10000' key2,
         'A1234' key3,
  from   dual
),
subTree as (
  select     tree.key1,
             tree.key2,
             tree.key3,

             tree.lkey1,
             tree.lkey2,
             tree.lkey3,

             tree.flag,

             connect_by_isleaf isLeaf,
             level thisLevel

  from       tree,
             queryKeys

  start with tree.key1 = queryKeys.key1
  and        tree.key2 = queryKeys.key2
  and        tree.key3 = queryKeys.key3

  connect by tree.key1 = prior tree.lkey1
  and        tree.key2 = prior tree.lkey2
  and        tree.key3 = prior tree.lkey3
),
maxTree as (
  select max(thisLevel) maxLevel
  from   subTree
)
select lkey1 key1,
       lkey2 key2,
       lkey3 key3,
       1 - isLeaf option,
       flag

from   subTree,
       maxTree
where (isLeaf = 1 or thisLevel = maxLevel - 1)
and   (length(key2) != length(lkey2) or substr(lkey2, 2, 1) != 'X');
Run Code Online (Sandbox Code Playgroud)

原因queryKeys是因为它在更大的查询中的其他地方使用,并且可以包含多个记录。该maxTree部分的问题,超出了一般的诡异!

现在,这篇文章的标题的原因是因为这种查询可以做很多更直接,如果我能指的是父母的FLAG领域。我尝试了一种JOIN方法来实现这个想法 - 在相关键上将树与自身连接 - 但是,除非我弄错了,否则会导致递归问题,您必须不断迭代树才能找到正确的父键(因为KEYxLKEYx字段都定义了记录的完整组合键)。

(PS 使用 Oracle 10gR2,如果有区别的话。)

art*_*rro 5

只需使用:

PRIOR FLAG 
Run Code Online (Sandbox Code Playgroud)

它会给你你想要的 - 父行的标志字段。

subTree as (            
select     tree.key1,            
         tree.key2,            
         tree.key3,            
         tree.lkey1,            
         tree.lkey2,            
         tree.lkey3,            
         tree.flag,            
         PRIOR TREE.FLAG PRIOR_FLAG
         connect_by_isleaf isLeaf,            
         level thisLevel            

from       tree,            
         queryKeys 
(...)
Run Code Online (Sandbox Code Playgroud)