由于有一个独特的列(如您所说,ID
),请查看是否有帮助:
- 将每一列拆分为行
- 使用2个
listagg
将它们重新组成(使用CASE
):
- 一个删除不需要的值
- 另一个对它们进行正确排序的方法(“将位置16的值放到位置4”)
请注意,我的结果与您的结果有所不同;如果我计算正确,则16666不在位置16处,而是在17处,因此-11512必须移至位置4。
我还添加了另一条 dummy 行,用于确认我是否正确计算了位置,并说明了为什么必须使用#10-12行(由于重复)。
好的,您在这里:
SQL> with test (id,col) as
2 (
3 select 1,'|||14444|10107|227931|10115||10118||11361|11485||10110||11512|16666|||' from dual union all
4 select 2,'1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20' from dual
5 ),6 temp as
7 (select replace(regexp_substr(col,'(.*?)(\||$)',1,column_value),'|','') val,8 column_value lvl,9 id
10 from test cross join table(cast(multiset(select level from dual
11 connect by level <= regexp_count(col,'\|') + 1
12 ) as sys.odcinumberlist))
13 )
14 select id,15 listagg(case when lvl in (4,6,8,9,11,12,13) then '|'
16 else val || case when lvl = 20 then '' else '|' end
17 end,'')
18 within group (order by case when lvl = 16 then 4
19 when lvl = 4 then 16
20 else lvl
21 end) result
22 from temp
23 group by id;
ID RESULT
---------- ------------------------------------------------------------
1 |||11512|10107||10115|||||||10110|||16666|||
2 1|2|3|16|5||7|||10||||14|15||17|18|19|20
SQL>
,
通过从字符串中删除要删除的数字的捕获组,然后将((\d*\|){2})
写为(\d*\|\d*\|)
,可以获得所需的结果。这样可以将捕获组的数量减少到7个,从而使您的代码按原样工作:
select regexp_replace(col1,'^(\d*\|\d*\|\d*\|\d*\|)\d*\|(\d*\|)\d*\|(\d*\|)\d*\|\d*\|(\d*\|)\d*\|\d*\|\d*\|(\d*\|\d*\|)(\d*\|)(.*)$','\1\6\2|\3||\4|||\5|\7') as cc
from table
输出(用于您的测试数据以及@Littlefoot好列示例):
CC
|||14444|16666|227931|||||11361|||||11512|||||
0|1|2|3|16|5||7|||10||||14|15||17|18|19|
Demo on dbfiddle
本文链接:https://www.f2er.com/3168503.html