按普通人分组递归循环

Grouping recursive cycle by common person

我是 PL/SQL 的新手,我正在努力完成我得到的任务。

我有法律实体和自然实体。每个法律实体都可以有一些自然实体,这些自然实体可以与 1 个或多个实体相关联。

结果应显示哪些公司通过一些不一致的因素联系在一起。实际上,关系更 "deep" 和复杂。 在我的示例中,结果应该是这样的:

excel 中的示例 table:

我做了 3 table秒:

CREATE GLOBAL TEMPORARY TABLE tbl_temp
(
   F_CL VARCHAR2(255) NULL,
   par NUMBER(5) NULL
)
ON COMMIT PRESERVE ROWS;

DECLARE
  party NUMBER := 1;
  r NUMBER := 1;

BEGIN
FOR CLUID IN (select FO_CLUID from snapshot_fo  WHERE ROWNUM =1)
LOOP
INSERT INTO tbl_temp (F_CL,par) VALUES (CLUID,party);

        WHILE  ( r> 0 )
        BEGIN

            MERGE INTO tbl_temp tg
            USING  ((SELECT distinct FO_CLUID from snapshot_vazba where PO_CLUID in (
                                                        SELECT distinct PO_CLUID 
                                                        from snapshot_vazba
                                                        where FO_CLUID in (select f_cl from tbl_temp where kod=party)
                                                    ))
            ) src
                on (tg.FO_cluid =src.FO_cluid)
            WHEN NOT MATCHED THEN
                INSERT (F_CL, par)
                VALUES (src.FO_CLUID, party)               
        SET r = SQL%ROWCOUNT
        END;
        INSERT INTO odlite (FO_CLUID, KOD) VALUES (tbl_temp.cluid,tbl_temp.party);
        delete from snapshot_fo where fo_cluid in (select fo_cluid from odlite);
        truncate table tbl_temp;
        party := party + 1;
        r := 1;
    END Loop;
end ;
/

那我就把 table odlite ON FO_cluid 加入我的 PO_cluid table。 但是代码目前不起作用......而且我不知道如何做。 如果有更简单的方法,请告诉我:)

PS: 由于公司限制,我不能在声明部分临时table。

提前致谢!

Oracle SQL 开发人员版本 19.2.1.247

我没有完全理解正确的任务,但你可能需要它

select t1.po_cluid, t2.kod
  from snapshot_vazba t1
  join odlite t2 on t2.fo_cluid = t1.fo_cluid
 group by t1.po_cluid, t2.kod
 order by po_cluid, kod

然后您可以使用合并、插入 select、for 循环,或输入一个集合并根据需要进行处理

select po_cluid, dense_rank() over (order by min(connect_by_root(rn))) kod
  from (select rownum rn, s.* from snapshot_vazba s) s
  connect by nocycle prior fo_cluid = fo_cluid or prior po_cluid = po_cluid
  group by po_cluid

dbfiddle demo

此查询 returns 需要输出,但是如果 table 很大,恐怕对您的数据库来说会很重。期待性能问题。它在公司 - 合作伙伴 - 公司之间循环并找到最小共同价值。 Dense_rank() 仅用于按顺序枚举值。

declare
  v_cluid varchar2(30 char);
  v_party integer;
  change_num integer;

  function get_party return integer is
    grp integer;
  begin
    select
      nvl(max(kod),0)
    into
      grp
    from
      snapshot_vazba;

    return grp;
  end;

  function get_cluid return varchar2 is
    v_cluid varchar2(30 char);
  begin
    select
      nvl(max(fo_cluid), 'XNA')
    into
      v_cluid
    from
      (
        select
          fo_cluid,
          row_number() over (partition by 1 order by count_f desc) as rn
        from
          (
            select count(1) as count_f, fo_cluid from snapshot_vazba where kod is null group by fo_cluid
          )
      )
    where
      rn = 1;

    return v_cluid;
  end;
begin
  v_party := get_party + 1;
  v_cluid := get_cluid;

  while (v_cluid <> 'XNA' )
  loop
    update
      snapshot_vazba
    set
      kod = v_party
    where
      po_cluid in (select po_cluid from snapshot_vazba where fo_cluid = v_cluid) and kod is null;

    update
      snapshot_vazba
    set
      kod = v_party
    where
      kod is null and
      fo_cluid in (select fo_cluid from snapshot_vazba where kod = v_party);

    change_num := sql%rowcount;

    while (change_num > 0)
    loop
      update
        snapshot_vazba
      set
        kod = v_party
      where
        po_cluid in (select po_cluid from snapshot_vazba where kod = v_party) and kod is null;

      update
        snapshot_vazba
      set
        kod = v_party
      where
        kod is null and
        fo_cluid in (select fo_cluid from snapshot_vazba where kod = v_party);

      change_num := sql%rowcount;

    end loop;

    commit;

    v_party := v_party + 1;  
    v_cluid := get_cluid;
  end loop;
end;
/

这有效:)