sql – 使用循环Oracle遍历每个ID的完整路径

前端之家收集整理的这篇文章主要介绍了sql – 使用循环Oracle遍历每个ID的完整路径前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个由ID,prev,当前和下一个节点(未排序)组成的输入数据.
我必须为覆盖所有遍历的节点的每个ID找到第一页和最后一页之间的路径.
例如:如果我的输入数据是:
第一列为ID,第二列为prev_node,第三列为当前节点,第四列为下一节点.
对于起始值,Prev_node为空,下一个节点对于最后一个值为空

输入

id prev current next
1 a b c
1 a e f
1 a b g
1 a b o
1 b c d
1 b g h
1 b o p
1 c d a
1 c b g
1 d a e
1 e f e
1 e f f
1 f e f
1 f f f
1 f f a
1 f a b
1 g h i
1 h i j
1 h j i
1 i j i
1 i i k
1 i k l
1 j i i
1 k l m
1 l m n
1 l n a
1 m n a
1 n a b
1 o p q
1 p q r
1 q r s
1 r s t
1 s t u
1 t u v
1 u v w
1 v w x
1 w x
1   a b

输出应该是当前节点的路径,如 –

ID current
1 a
1 b
1 c
1 d
1 a
1 e
1 f
1 e
1 f
1 f
1 f
1 a
1 b
1 b
1 g
1 h
1 i
1 j
1 j
1 i
1 i
1 k
1 l
1 m
1 n
1 n
1 a
1 b
1 o
1 p
1 q
1 r
1 s
1 t
1 u
1 v
1 w
1 x

在这里我将有很多ID与类似的数据,我只显示一个ID(1).此外,我也使用了字母长度为200-500字符的字母.我尝试了sql方法,几乎​​没有修改,如果一个ID具有100行或更少的行,但为更多行(甚至将长字符串转换为数字)后给出字符串连接错误,它的工作正常.任何人都可以建议一种基于程序的强大的方法.我尝试了一些,但对于一个ID超过300行,它不起作用.
我有时会遇到以下代码错误是“字符串连接的结果太长”

我的代码

create or replace procedure pathing 
as 
  type varr is table of varchar(4000);
  visit varr;

  t number;
  --v varchar2(40);
  fp varchar2(1000);
  np varchar2(1000);

  type stype is  record(fp varchar2(1000),np varchar2(1000),t number);
  type sinput is table of stype;
  iarray sinput;

begin

  select id  
  bulk collect into visit 
  from table_source 
  group by id 
  order by count(1) desc;

  delete from table_final;
  commit;

  for k in visit.first .. visit.last loop

    delete from table_temp;
    commit;

    insert into table_temp
    select distinct prev_pg,page_id,next_pg,visit(k)  
    from table_source  
    where visit_id = visit(k) 
    order by prev_pg desc;

    commit;

    insert into table_final 
    WITH t_n AS ( 
      SELECT prev_pg,rownum n FROM table_temp
    ),t_br AS (
      SELECT 
        prev_pg,'<' || listagg(n,'|<') within GROUP(ORDER BY n) || '|' br,COUNT(0) cnt
    FROM 
      t_n
    GROUP BY 
      prev_pg,page_id
    ),t_mp AS (
      SELECT 
        '|' || listagg(list) within GROUP(ORDER BY NULL) list
      FROM ( 
        SELECT REPLACE(br,'<') list FROM t_br WHERE cnt > 1
      )
    ),t_path(step,used) AS ( 
        SELECT 1,'' 
        FROM t_n 
        WHERE prev_pg is null
      UNION ALL
        SELECT 
         step + 1,t_br.page_id,t_n.next_pg,CASE
           WHEN instr(list,'|' || n || '|') = 0
            THEN used
            ELSE used || n || '|'
          END
       FROM 
         t_mp,t_path
         JOIN t_br
           ON next_pg = t_br.page_id AND t_path.page_id = prev_pg
         JOIN t_n
           ON n = regexp_substr(br,'^(<(' || used || '0)\|)*(<(\d+))?',1,'',4)
    ) cycle step
    SET is_cycle TO 'Y' DEFAULT 'N'
    SELECT 
      page_id,step,visit(k)  
    FROM t_path 
    ORDER BY 1;

    commit;

  end loop;
end;

更详细地解释我的例子: – 我想要每个ID的全路径旅程,在我以ID 1为例的例子中.对于ID 1,我们有一组当前,上一个和下一个值.所以我们需要找到使用这些值的路径.例如对于id 1,路径以’a’开头,因为prev列为空.那么我们看到a的下一个值是b,即当前是a,而next是b,所以我们在id的所有行中搜索prev值作为a和当前值作为b,在我们找到相同的地方我们采取下一个该行的值并重复该过程.例如这里prev a,当前b和next是c,所以我们再次搜索prev b和当前c等等,直到我们获得完整路径,直到我们遇到下一个为null,就像最后一个

解决方法

通过分层查询子句的解决方案似乎是棘手的,但是应该有一个解决方案,作为替代方案,使用现有的PL / sql代码,但是将VARCHAR字段更改为CLOB以避免“字符串连接的结果太长”.
原文链接:https://www.f2er.com/mssql/75783.html

猜你在找的MsSQL相关文章