Als ik het goed begrijp hoef je niet alleen ',' te vervangen door een spatie, maar ook om duplicaten op een slimmere manier te verwijderen.
Als ik die uitdrukking aanpas om met spatie te werken in plaats van ',', krijg ik
select regexp_replace('A B A A C D' ,'([^ ]+)( [ ]*\1)+', '\1') from dual
wat 'A B A C D'
. geeft , niet wat je nodig hebt.
Een manier om het gewenste resultaat te krijgen kan de volgende zijn, een beetje ingewikkelder:
with string(s) as ( select 'A B A A C D' from dual)
select listagg(case when rn = 1 then str end, ' ') within group (order by lev)
from (
select str, row_number() over (partition by str order by 1) rn, lev
from (
SELECT trim(regexp_substr(s, '[^ ]+', 1, level)) str,
level as lev
FROM string
CONNECT BY instr(s, ' ', 1, level - 1) > 0
)
)
Mijn grootste probleem hier is dat ik geen regexp kan bouwen die controleert op niet-aangrenzende duplicaten, dus ik moet de string splitsen, controleren op duplicaten en dan de niet-gedupliceerde waarden opnieuw aggregeren, waarbij de volgorde behouden blijft.
Als u de volgorde van de tokens in de resultaatreeks niet erg vindt, kan dit worden vereenvoudigd:
with string(s) as ( select 'A B A A C D' from dual)
select listagg(str, ' ') within group (order by 1)
from (
SELECT distinct trim(regexp_substr(s, '[^ ]+', 1, level)) as str
FROM string
CONNECT BY instr(s, ' ', 1, level - 1) > 0
)