暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle 我的问题可以通过使用分层查询来解决吗?

askTom 2018-06-01
259

问题描述

你好,我有这个问题,我到目前为止还没有解决,尽管我怀疑它应该使用分层查询。

我在保存和共享的LiveSQL脚本中包含了示例/测试数据,为方便起见,它包括假设查询将为每行返回的所需结果,在列expected_master_group2中。

确定结果的要求:

我们有这个表,每一行都有group1和group2值 (从不空或空)。
我们希望使用sql为他们中的每一个找到group1的 “主” (因为缺少更好的单词) group2值,考虑到:

1-对于给定的group1值,我们可以有一个或多个group2值。
2-对于给定的group2值,我们可以有一个或多个group1值。
3-如果group1具有单个group2,并且该group2也具有此单个group1相关,则我们的主group2将是group2。
4-如果group1具有许多group2,但是这些group2中的每一个都没有链接到任何其他group1,则group1的min(group2) 将是主group2。
5-如果一个group1有一个或多个group2,如果这些group2中的任何一个链接到一个或多个其他group1,那么我们需要找到那些其他链接的group1,找到它们是否本身链接到我们已经见过的不同group2,等等,在找到所有group2之前,我们可能会与给定的group1联系起来。然后,主group2将是我们通过遍历所有这些关系创建的列表中的min(group2)。

例如,要确定对于具有group1 = 129653的行,我要构建的查询 (并放入expected_master_group2) 要检索的预期结果为 “4190412”:

-具有group1 = 129653的两个行都具有group2 = '4190414 '。
-group2 = '4190414 '还与具有group1 = 129654的行有关。
-有2行具有group1 = 129654,一行具有group2 = '4190414 '(我们已经 “看到” 了),一行具有group2 = '4190413'。
-group2 = '4190413 '与3行相关,分别具有group1 = 129653 (已经看到) 、129654 (已经看到) 和129669。
-group1 = 129669与group2的 “4190413” (已经看到) 和 “4190412” 有关
-group2 = “4190412” 与group1的129668,129670和129669有关 (已经看到)
-group1s 129668,129670只有group2 = '4190412 ',我们已经完成了遍历关系。
-我们已经看到了group2的 “4190414”,“4190413” 和 “4190412”。
-Group2'4190412 '是我们见过的所有group2s中最小的,这是我要寻找的结果,对于具有group1 = 129653的行。


我希望我的解释足够清楚和透彻。

谢谢。


专家解答

是的。你可以使用递归与沿着层次结构走。搜索与当前中相应值匹配的下一行的group1或group2值。

group2的几个值有很多行。因此,如果您所做的只是上面的检查,您将继续回到相同的g2值。这意味着一遍又一遍地重新审视g1值...这会爆炸您的层次结构,使查询取f o r e v e r。

您可以通过跟踪您访问的先前g1/g2值来避免这种情况。如果下一行的任何一个值与源的值匹配,请不要返回。

把它们放在一起,你会得到:

with s_data as (
  select distinct * from sample_data
), tree ( g1, g2, g1_orig, g2_orig, rt, expect ) as (
  select group1, group2, 0, '0', group1, expected_master_group2
  from   s_data
  union  all
  select s.group1, s.group2, t.g1, t.g2, t.rt , expect
  from   tree t
  join   s_data s
  on     ( ( t.g1 = s.group1 ) or ( t.g2 = s.group2 ) )
  and    ( t.g1_orig <> s.group1 and t.g2_orig <> s.group2 ) 
) 
  select rt, expect, min ( g2 ),
         case
           when expect = min ( g2 ) then 'SUCCESS!'
           else 'FAIL :('
         end is_correct
  from   tree
  group  by rt, expect;

RT       EXPECT     MIN(G2)    IS_CORRECT   
  129654 4190412    4190412    SUCCESS!     
  129659 4188693    4188693    SUCCESS!     
  129668 4190412    4190412    SUCCESS!     
  129676 4188693    4188693    SUCCESS!     
  129670 4190412    4190412    SUCCESS!     
  129660 4188693    4188693    SUCCESS!     
  129674 4188693    4188693    SUCCESS!     
  129653 4190412    4190412    SUCCESS!     
  129658 4188693    4188693    SUCCESS!     
  129655 4188693    4188693    SUCCESS!     
  129656 4188693    4188693    SUCCESS!     
  129678 4188693    4188693    SUCCESS!     
  129671 4188693    4188693    SUCCESS!     
  129672 4188693    4188693    SUCCESS!     
  129673 4188693    4188693    SUCCESS!     
  129669 4190412    4190412    SUCCESS!     
  129657 4188693    4188693    SUCCESS!     
  129677 4188693    4188693    SUCCESS!     
  129679 11219712   11219712   SUCCESS!     
  129675 4188693    4188693    SUCCESS! 
复制


HT对Kim Berg Hansen的递归子查询图遍历是这个答案的灵感来源:https://www.kibeha.dk/2013/01/recursive-subquery-graph-traversing.html
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论