如何在这个查询中摆脱'ORA-01489:字符串连接的结果太长'?

cor*_*pro 6 sql oracle optimization

此查询获取网络中的主导集.所以例如给定一个网络

A<----->B
B<----->C
B<----->D
C<----->E
D<----->C
D<----->E
F<----->E

它返回
B,E
B,F
A,E
但它不适用于大数据,因为我在我的结果中使用字符串方法.我一直在尝试删除字符串方法并返回视图或其他东西,但无济于事

With t as (select 'A' as per1, 'B' as per2 from dual union all
         select 'B','C' from dual union all
         select 'B','D' from dual union all
         select 'C','B' from dual union all
         select 'C','E' from dual union all
         select 'D','C' from dual union all
         select 'D','E' from dual union all
         select 'E','C' from dual union all
         select 'E','D' from dual union all
         select 'F','E' from dual)
 ,t2 as (select distinct least(per1, per2) as per1, greatest(per1, per2) as per2 from t union
       select distinct greatest(per1, per2) as per1, least(per1, per2) as per1 from t)
 ,t3 as (select per1, per2, row_number() over (partition by per1 order by per2) as rn from t2)
 ,people as (select per, row_number() over (order by per) rn
             from (select distinct per1 as per from t union
                   select distinct per2 from t)
            )
  ,comb   as (select sys_connect_by_path(per,',')||',' as p
              from   people
              connect by rn > prior rn
             )
  ,find   as (select p, per2, count(*) over (partition by p) as cnt
             from (
                   select distinct comb.p, t3.per2
                   from   comb, t3
                   where  instr(comb.p, ','||t3.per1||',') > 0 or instr(comb.p, ','||t3.per2||',') > 0
                  )
            )
 ,rnk as (select p, rank() over (order by length(p)) as rnk
          from find
          where cnt = (select count(*) from people)
          order by rnk
         )  select distinct trim(',' from p) as p from rnk  where rnk.rnk = 1`
Run Code Online (Sandbox Code Playgroud)

APC*_*APC 6

Oracle的一个限制是SQL无法处理大于4000个字符的VARCHAR2.如果你试图返回超过这个大小的字符串,它会抛出ORA-01489.理想情况下,您应该尝试将结果集分解为多个小行.或者,您可以将其作为CLOB返回.

编辑

我如何将上述内容作为CLOB返回

嗯...

密切关注您的代码后,我认为唯一可以投掷ORA-1489的地方是这一行:

select sys_connect_by_path(per,',')||',' as p
from   people
Run Code Online (Sandbox Code Playgroud)

将该调用包装起来很容易TO_CLOB().不幸的是,将P转换为CLOB会破坏一些后续处理('p'的独特p ,分区),因此它可能不是一个选项.抱歉.

至于其他解决方法....

您的站点是否拥有Oracle Spatial许可证?我知道没有多少网站可以做,但如果你的网站是幸运网站之一(并且你使用的是10gR2或更高版本),那么你应该查看Oracle Spatial网络数据模型(PDF).

否则,如果无法限制sys_connect_by_path()调用的输出,则可能只需在PL/SQL中实现此操作.您可以使用PIPELINED FUNCTION返回最终输出,这样您仍然可以从SELECT语句中调用它.


小智 0

根据我的经验,您不想在大型、复杂的查询中进行复杂的字符串处理,而这个查询非常复杂。我猜想这个问题很可能受益于重新思考和不同的方法,而不是现有查询的优化。

底层表格是什么样的?您到底想实现什么目标?是否可以改变数据模型?