Om jag förstår väl behöver du inte bara ersätta ',' med ett mellanslag, utan också ta bort dubbletter på ett smartare sätt.
Om jag ändrar uttrycket så att det fungerar med rymden istället för ',' får jag
select regexp_replace('A B A A C D' ,'([^ ]+)( [ ]*\1)+', '\1') from dual
vilket ger 'A B A C D'
, inte vad du behöver.
Ett sätt att få ditt önskade resultat kan vara följande, lite mer komplicerat:
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
)
)
Mitt största problem här är att jag inte kan bygga ett regexp som letar efter icke-angränsande dubbletter, så jag måste dela upp strängen, leta efter dubbletter och sedan aggregera de icke-duplicerade värdena igen, hålla ordningen.
Om du inte har något emot ordningen på tokens i resultatsträngen, kan detta förenklas:
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
)