我的任务是将给定字符串中的相似数字/字符分组,
例如:
字符串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
。
帮助我,欢迎所有正则表达式查询。
答案 0 :(得分:9)
对救援的反思:
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&#39; s),整个模式(((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