我的任务是将给定字符串中的相似数字/字符分组,
例如:
字符串4455599的SQL的输出应为44 555 99,并且正在使用以下查询:

with t(str)
as (
  select '4455599' from dual
)
select listagg(str_grouped ,' ') within group (order by rownum) str_split
from(
    select listagg ( str) within group ( order by lvl) str_grouped
    from(
        select level lvl,
               substr(str,level,1) str,
               dense_rank() over( order by substr(str,level,1)) drank_no
        from t
          connect by level <= length(str)
    )
 group by drank_no
  );


但是由于我当前正在使用dense_rank,因此查询失败并显示以下数据。

445559944,预期为44 555 99 44,但为4444 555 99

bb119911,预期为bb 11 99 11,但为1111 99 bb

帮助我,欢迎所有正则表达式查询。

最佳答案

对救援的反向引用:

select
    regexp_replace('4455599', '((.)\2*)', '\1 ')
from dual;


输出:

44 555 99


说明

((.)\2*)定义两个捕获组,其中:

(.)匹配任何单个字符并将其捕获到组2中。

\2*是对第2组中捕获的字符的后向引用,该字符与同一字符匹配零次或多次。

因此,((.)\2*)与一个或多个相同字符的序列匹配,并捕获组1中的序列。

\1 替换与组1的内容匹配的字符,后跟一个空格。

反向引用从1开始从左到右计数(第0组是整个匹配项)。因此,如果您具有模式(((a)b)c)d,则最里面的(a)是组3,((a)b)是组2,(((a)b)c)是组1,如果您使用的是普通的正则表达式引擎(不是oracle的),则整个模式(((a)b)c)d在组0中捕获。

测试用例

select
    val, regexp_replace(val, '((.)\2*)', '\1 ') as result
from (
    select '445559944' as val from dual
    union all select 'bb119911' as val from dual
    union all select '46455599464' as val from dual
) foo;


输出:

VAL         RESULT
----------- ------------------
445559944   44 555 99 44
bb119911    bb 11 99 11
46455599464 4 6 4 555 99 4 6 4

07-25 21:10
查看更多