【问题标题】:Is a recursive query possible?递归查询可能吗?
【发布时间】:2021-12-17 04:13:15
【问题描述】:

一个对我来说似乎很简单的 Oracle SQL 问题,但我做不到(无需手动进行多次连续查询)...我想使用 SQL“递归”方法或任何其他可以避免的方法我手动使用“n”次相同的查询。

这是我的数据的一个非常简化的示例:

row ID Value Result
1 135 AAA AAA
2 246 BBB BBB
3 357 135 AAA
4 468 357 AAA
5 578 EEE EEE

如果一个值引用了一个 ID,那么我们需要获取该 ID 的值。如果一个 ID 的值是另一个 ID,那么您必须继续寻找“真实”值。如果值不是ID,那么我们可以直接取。

“结果”列给出了预期的结果:

对于第 3 行,您必须查找 ID 135 的值。

对于第 4 行,你必须得到 ID 357 的值,它对应于 ID 135 的值。

在这里,我不想做的事情:

with my_data as(
    select '135' as id, 'AAA' as value from dual union all
    select '246', 'BBB' from dual union all
    select '357', '135' from dual union all
    select '468', '357' from dual union all
    select '578', 'EEE' from dual
)
,step as(
    select d1.*
          ,nvl((select d2.value from my_data d2 where d1.value=d2.id),d1.value) as step_1
    from my_data d1
)
-- steps to do again and again...
select step.*
      ,nvl((select my_data.value from my_data where step.step_1=my_data.id),step.step_1) as step_n
from step
order by 1
;

感谢您的帮助。


除了Carlos S anwser:

它完全符合我在“非常简化”示例中的要求。但是,对于真实数据的子集,出现了问题(数据有点过多)。另一方面,如果我删除引用 ID 的结果,它会给出我想要的结果。我找不到问题。

注意:如我最初的示例所示,ID 将始终以数字开头,而“真实”值将始终以字母开头。所以正则表达式策略是“好的”。

这是一个真实的例子:

with my_data as(
    select '116554226_2' as id, '116554226_1' as value from dual union all
    select '119675285_2' as id, '119675285_1' as value from dual union all
    select '119675285_3' as id, '119675285_2' as value from dual union all
    select '13656777_1' as id, '119675471_1' as value from dual union all
    select '13656777_5001' as id, '119675471_1' as value from dual union all
    select '13656777_2' as id, '13656777_1' as value from dual union all
    select '13656155_1' as id, '13657581_1' as value from dual union all
    select '13657581_2' as id, '13657581_1' as value from dual union all
    select '13657015_1' as id, '13657759_1' as value from dual union all
    select '13657759_2' as id, '13657759_1' as value from dual union all
    select '116554226_1' as id, '471502681_1' as value from dual union all
    select '462721769_1' as id, 'O7X5J' as value from dual union all
    select '471502681_1' as id, 'T3L8L' as value from dual union all
    select '119675471_1' as id, 'T8Q0G' as value from dual union all
    select '119675471_5001' as id, 'T8Q0G' as value from dual union all
    select '116555133_1' as id, 'T9J2Q' as value from dual union all
    select '13657581_1' as id, 'U5H5Z' as value from dual union all
    select '119674049_1' as id, 'Y5G7V' as value from dual union all
    select '13657759_1' as id, 'Z0Y9C' as value from dual union all
    select '119675285_1' as id, 'Z7E0D' as value from dual
)
SELECT my_data.*, CONNECT_BY_ROOT value result
FROM   my_data
CONNECT BY PRIOR id = value 
START WITH REGEXP_LIKE(value,'[^0-9]')
;

盒装数据是不需要的,否则它下面的一切都可以。

【问题讨论】:

    标签: oracle11g recursive-query


    【解决方案1】:

    我认为这个查询可能会对您有所帮助:

    with my_data as(
      select '135' as id, 'AAA' as value from dual union all
      select '246', 'BBB' from dual union all
      select '357', '135' from dual union all
      select '468', '357' from dual union all
      select '578', 'EEE' from dual
    )
    SELECT rownum, id, value, CONNECT_BY_ROOT value result
    FROM   my_data
    CONNECT BY PRIOR id = value 
    START WITH REGEXP_LIKE(value,'[^0-9]')
    
    ROWNUM ID VALUE RESULT
    1 135 AAA AAA
    2 357 135 AAA
    3 468 357 AAA
    4 246 BBB BBB
    5 578 EEE EEE

    【讨论】:

    • 在我的示例中运行良好,但不适用于我的真实数据。我将为您提供这些真实数据的一个子集。
    • 哼,我想我找到了。正则表达式是问题,替换为: START WITH NOT REGEXP_LIKE(value,'^[0-9]')
    • 如果“ID 总是以数字开头”,那么:START WITH REGEXP_LIKE(value,'^[^0-9]')
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-25
    • 1970-01-01
    • 2021-06-09
    • 1970-01-01
    • 2012-02-08
    相关资源
    最近更新 更多