我的数据如下所示:
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
这是分层数据,我将查询根复合键(在本例中09/10 10000 A1234
);该FLAG
字段是指由LKEYx
键标识的“对象”。可以有任意数量的嵌套级别。(请注意,KEY1
andKEY3
字段不必像上面的示例中那样保持不变,只要保留层次结构即可。)
我要检索的是叶子节点,但是如果叶子的父节点与第二个字符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
我写了一个这样的查询,但它并不漂亮。此外,为了区分可选记录,它假设所有叶子节点都在树的同一层;但是,这不一定是正确的。我的查询如下:
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');
原因queryKeys
是因为它在更大的查询中的其他地方使用并且可以包含多个记录。maxTree
部分是问题,超出了一般的怪癖!
现在,这篇文章标题的原因是因为如果我可以引用父字段,这个查询可以更直接。FLAG
我尝试了一种JOIN
方法来实现这个想法——在相关键上将树与自身连接——但是,除非我弄错了,否则会导致递归问题,你必须不断迭代树才能找到正确的父键(因为KEYx
和LKEYx
字段都定义了记录的完整组合键)。
(PS 使用 Oracle 10gR2,如果它有所作为。)