Oracle SQL递归查找非空列值的第一个实例

时间:2013-07-11 11:39:32

标签: sql oracle recursion hierarchical-data

我会尝试解释如何布置表格,以便我需要的内容可能更清晰。

###############################################################
# cid # iid # child cid # child iid # target cid # target iid #
############################################################### 
# 112 # 1   # null      # null      # 116        # 1          #
# 112 # 2   # 112       # 1         # null       # null       #
# 112 # 3   # 112       # 1         # 116        # 2          #
# 112 # 4   # 112       # 1         # 100        # 3          #
# 112 # 101 # null      # null      # 116        # 101        #
# 112 # 102 # 112       # 101       # null       # null       #
# 112 # 103 # 112       # 101       # 116        # 102        #
# 112 # 201 # null      # null      # 116        # 201        #
# 112 # 202 # 112       # 201       # null       # null       #
# 112 # 203 # 112       # 201       # 116        # 202        #
# 112 # 301 # null      # null      # 116        # 301        #
# 112 # 302 # 112       # 301       # null       # null       #
# 112 # 302 # 112       # 301       # 116        # 302        #

上面有一个我正在尝试从中获取数据的表格的缩减表示。对不起,如果布局有点废话。这里的每一行都是一个对象。这些对象中的每一个都可以具有子对象,例如,第一行没有子对象但是链接到目标对象。第二行有一个子对象,并没有链接到目标对象,但是,它通过子cid链接回第1行,而iid则有一个目标对象。第三行也链接到第一行,但它也有一个目标对象,所以我实际上并不想回到第一行。

其他表格

#########################################
# cid # iid # col1 # col2 # col3 # col4 #
#########################################
# 116 # 1   # a    # null # 16   # 1    #
# 116 # 2   # b    # 1    # 6    # null #
# 116 # 3   # n    # 1    # 11   # 2    #
# 116 # 101 # n    # 2    # 61   # 3    #
# 116 # 102 # b    # null # 161  # 101  #
# 116 # 201 # a    # 33   # 312  # 116  # 
# 116 # 202 # a    # 33   # 312  # 116  # 
# 116 # 301 # s    # 56   # 1321 # 33   #
# 116 # 302 # r    # 6    # 22   # 12   #

结果表

###########################################################################################
# cid # iid # child cid # child iid # target cid # target iid # col1 # col2 # col3 # col4 #
###########################################################################################
# 112 # 1   # null      # null      # 116        # 1          # a    # null # 16   # 1    #
# 112 # 2   # 112       # 1         # null       # null       # a    # null # 16   # 1    #
# 112 # 3   # 112       # 1         # 116        # 2          # b    # 1    # 6    # null #
# 112 # 4   # 112       # 1         # 100        # 3          # n    # 1    # 11   # 2    #
# 112 # 101 # null      # null      # 116        # 101        # n    # 2    # 61   # 3    #
# 112 # 102 # 112       # 101       # null       # null       # n    # 2    # 61   # 3    #
# 112 # 103 # 112       # 101       # 116        # 102        # b    # null # 161  # 101  #
# 112 # 201 # null      # null      # 116        # 201        # a    # 33   # 312  # 116  #
# 112 # 202 # 112       # 201       # null       # null       # a    # 33   # 312  # 116  #
# 112 # 203 # 112       # 201       # 116        # 202        # a    # 33   # 312  # 116  # 
# 112 # 301 # null      # null      # 116        # 301        # s    # 56   # 1321 # 33   #
# 112 # 302 # 112       # 301       # null       # null       # s    # 56   # 1321 # 33   #
# 112 # 302 # 112       # 301       # 116        # 302        # r    # 6    # 22   # 12   #

[只是为了澄清,在第一个表格中,目标cid和iid与另一个表格中的cid和iid相关联。]

基本上我需要的是递归地返回表,直到一行有一个目标对象引用。

如果一行同时包含子c / i id和目标c / i id,我只想要目标c / i id。

有人能指出我正确的方向吗?

我正在慢慢阅读 http://docs.oracle.com/cd/B19306_01/server.102/b14200/queries003.htm但我发现它有点令人困惑。我不会完全成为更简单的SQL查询的专家,所以递归现在有点过头了。

由于

编辑:添加了其他表和结果的示例

1 个答案:

答案 0 :(得分:3)

我不知道你到底需要什么,但是 你可以从这个陈述开始

select cid, iid, level, connect_by_root(target_cid), connect_by_root(target_iid)
from tab
connect by    prior cid = child_cid
          AND prior iid = child_iid
          AND target_cid is null          
; 

然后填写您需要的条目

select *
from 
(
select cid, iid, level, connect_by_root(target_cid) as target_cid, connect_by_root(target_iid) as target_iid
from tab
connect by    prior cid = child_cid
          AND prior iid = child_iid
          AND target_cid is null          
)
where target_cid is not null
;          

    CID IID TARGET_CID TARGET_IID
    ++++++++++++++++++++++++++++++
    112 1     116         1
    112 2     116         1
    112 3     116         2
    112 4     100         3
    112 101   116         101
    112 102   116         101
    112 103   116         102
    112 201   116         201
    112 202   116         201
    112 203   116         202
    112 301   116         301
    112 302   116         301
    112 302   116         302