Ось як вирішити вашу проблему.
select
regexp_replace(
'2,2,2.1,3,3,3,3,4,4'
,'([^,]+)(,\1)*(,|$)', '\1\3')
from dual
повертається
2,2,1,3,4
З Oracle 19C він вбудований див. Тут
Починаючи з 18C і раніше спробуйте в групі дивіться тут
В іншому випадку використовуйте регулярні вирази
ВІДПОВІДЬ нижче:
select col1,
regexp_replace(
listagg(
col2 , ',') within group (order by col2) -- sorted
,'([^,]+)(,\1)*(,|$)', '\1\3') )
from tableX
where rn = 1
group by col1;
Примітка: Вищевказане спрацює в більшості випадків - список слід сортувати, можливо, вам доведеться обрізати весь кінцевий та провідний простір залежно від ваших даних.
Якщо у вас багато елементів у групі> 20 або великі розміри рядків, ви можете зіткнутися з обмеженням розміру рядка оракула «результат об’єднання рядків занадто довгий».
В Oracle 12cR2 ви можете придушити цю помилку, див. Тут . В якості альтернативи можна вказати максимальне число членів кожної групи. Це спрацює, лише якщо нормально перерахувати лише перших членів. Якщо у вас дуже довгі змінні рядки, це може не спрацювати. доведеться експериментувати.
select col1,
case
when count(col2) < 100 then
regexp_replace(
listagg(col2, ',') within group (order by col2)
,'([^,]+)(,\1)*(,|$)', '\1\3')
else
'Too many entries to list...'
end
from sometable
where rn = 1
group by col1;
Ще одне рішення (не так просто), ми сподіваємося уникнути оракула обмеження на розмір рядка - розмір рядка обмежена 4000. Завдяки цьому повідомленню тут по user3465996
select col1 ,
dbms_xmlgen.convert( -- HTML decode
dbms_lob.substr( -- limit size to 4000 chars
ltrim( -- remove leading commas
REGEXP_REPLACE(REPLACE(
REPLACE(
XMLAGG(
XMLELEMENT("A",col2 )
ORDER BY col2).getClobVal(),
'<A>',','),
'</A>',''),'([^,]+)(,\1)*(,|$)', '\1\3'),
','), -- remove leading XML commas ltrim
4000,1) -- limit to 4000 string size
, 1) -- HTML.decode
as col2
from sometable
where rn = 1
group by col1;
V1 - деякі тестові приклади - FYI
regexp_replace('2,2,2.1,3,3,4,4','([^,]+)(,\1)+', '\1')
-> 2.1,3,4 Fail
regexp_replace('2 ,2 ,2.1,3 ,3 ,4 ,4 ','([^,]+)(,\1)+', '\1')
-> 2 ,2.1,3,4 Success - fixed length items
V2 - елементи, що містяться в елементах, наприклад. 2,21
regexp_replace('2.1,1','([^,]+)(,\1)+', '\1')
-> 2.1 Fail
regexp_replace('2 ,2 ,2.1,1 ,3 ,4 ,4 ','(^|,)(.+)(,\2)+', '\1\2')
-> 2 ,2.1,1 ,3 ,4 -- success - NEW regex
regexp_replace('a,b,b,b,b,c','(^|,)(.+)(,\2)+', '\1\2')
-> a,b,b,c fail!
v3 - регулярний вираз дякую Ігореві! працює всі справи.
select
regexp_replace('2,2,2.1,3,3,4,4','([^,]+)(,\1)*(,|$)', '\1\3') ,
---> 2,2.1,3,4 works
regexp_replace('2.1,1','([^,]+)(,\1)*(,|$)', '\1\3'),
--> 2.1,1 works
regexp_replace('a,b,b,b,b,c','([^,]+)(,\1)*(,|$)', '\1\3')
---> a,b,c works
from dual