【问题标题】:Reorder Parent-child relationship in same table - Oracle SQL在同一个表中重新排序父子关系 - Oracle SQL
【发布时间】:2020-06-16 15:31:20
【问题描述】:

我在名为 CPGRPRULREL 的表中有以下数据。

CPGRPRULREL_NUM | CPGRPRULREL_NUM_PRIOR | STATUS     | CNDQUALSRC_CD | CNDQUALTYP_CD | CPGRP_NUM
--------------------------------------------------------------------------------------------------
41292           | 41289                 | Active     | PRODCNT       | PRODCNTUNQ    | 
41289           | 41286                 | Superseded | OTHERPG       |               | 118729
41286           | 41283                 | Superseded | SUBM          | VOLUME        | 
41283           | 41280                 | Superseded | OTHERPG       |               | 118729
41280           | 41277                 | Superseded | OTHERPG       |               | 118729
41277           | null                  | Superseded | PRODCNT       | PRODCNTALL    | 

这里,CPGRPREL_NUM_PRIOR 是指向 CPGRPRULREL_NUM 的链接(即具有外键约束 - 一种父子关系)。

我想删除所有 CPGRP_NUM = 118729。在此之前,我需要更新剩余行的 CPGRPRULREL_NUM_PRIOR 的值,以便正确链接保持不变。

我需要更新查询,它只会更新具有 CPGRP_NUM 118729 的行,并且在运行更新后具有以下数据。

CPGRPRULREL_NUM | CPGRPRULREL_NUM_PRIOR | STATUS     | CNDQUALSRC_CD | CNDQUALTYP_CD | CPGRP_NUM
--------------------------------------------------------------------------------------------------
41292           | 41286                 | Active     | PRODCNT       | PRODCNTUNQ    | 
41289           | 41286                 | Superseded | OTHERPG       |               | 118729
41286           | 41277                 | Superseded | SUBM          | VOLUME        | 
41283           | 41280                 | Superseded | OTHERPG       |               | 118729
41280           | 41277                 | Superseded | OTHERPG       |               | 118729
41277           | null                  | Superseded | PRODCNT       | PRODCNTALL    |            

请注意,CPGRPREL_NUM 为 41292 和 41286 的 2 行已更新 CPGRPRULREL_NUM_PRIOR。

【问题讨论】:

  • 为什么CPGRPRULREL_NUM = 41283没有更新到41277?
  • 我打算删除所有 CPGRP_NUM = 118729 的行。所以即使 CPGRPRULREL_NUM = 41283 没有更新也可以。目的是即使在删除 CPGRP_NUM = 118729 的行之后也能建立传播的父子关系。

标签: sql oracle foreign-keys parent-child hierarchical-data


【解决方案1】:

所以你想得到以前的CPGRPRULREL_NUMCPGRP_NUM <> 118729?

这样的事情应该可以工作:

  • 构建树,从第一个(null prior)开始
  • 如果之前的CPGRP_NUM 是118729,那么:
    • 如果为 null,则返回之前的 CPGRPRULREL_NUM_PRIOR 或 CPGRPRULREL_NUM

给予:

with rws as (
  select 41292 num, 41289 num_prior, null cpgrp_num from dual union all
  select 41289 num, 41286 num_prior, 118729 from dual union all
  select 41286 num, 41283 num_prior, null from dual union all
  select 41283 num, 41280 num_prior, 118729 from dual union all
  select 41280 num, 41277 num_prior, 118729 from dual union all
  select 41277 num, null  num_prior, null from dual 
), tree ( num, num_prior, cpgrp_num ) as (
  select * from rws
  where  num_prior is null
  union all
  select r.num, 
         case
           when t.cpgrp_num = 118729 then nvl ( t.num_prior, t.num ) 
           else r.num_prior
         end num_prior, r.cpgrp_num 
  from   rws r
  join   tree t
  on     t.num = r.num_prior
)
  select * from tree;

NUM         NUM_PRIOR    CPGRP_NUM   
   41277       <null>       <null> 
   41280        41277       118729 
   41283        41277       118729 
   41286        41277       <null> 
   41289        41286       118729 
   41292        41286       <null>

【讨论】:

    【解决方案2】:

    使用分层子查询查找每个条目的叶值:

    update cpgrprulrel c
      set CPGRPRULREL_NUM_PRIOR =
        (select CPGRPRULREL_NUM_PRIOR from cpgrprulrel
          where connect_by_isleaf = 1
          start with CPGRPRULREL_NUM = c.CPGRPRULREL_NUM_prior and cpgrp_num = 118729
          connect by prior CPGRPRULREL_NUM_prior = CPGRPRULREL_NUM and cpgrp_num = 118729)
      where cpgrp_num is null
    

    dbfiddle

    然后你可以删除不需要的行。

    【讨论】:

      猜你喜欢
      • 2019-04-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多