如果重复值不相邻,我认为您不能仅使用 regexp_replace 来做到这一点。一种方法是将值拆分,消除重复项,然后将它们重新组合在一起。
标记分隔字符串的常用方法是使用regexp_substr 和connect by 子句。在字符串中使用绑定变量可以使代码更清晰:
var value varchar2(100);
exec :value := 'Ian,Beatty,Larry,Neesha,Beatty,Neesha,Ian,Neesha';
select regexp_substr(:value, '[^,]+', 1, level) as value
from dual
connect by regexp_substr(:value, '[^,]+', 1, level) is not null;
VALUE
------------------------------
Ian
Beatty
Larry
Neesha
Beatty
Neesha
Ian
Neesha
您可以将其用作子查询(或 CTE),从中获取不同的值,然后使用 listagg 重新组合它:
select listagg(value, ',') within group (order by value) as value
from (
select distinct value from (
select regexp_substr(:value, '[^,]+', 1, level) as value
from dual
connect by regexp_substr(:value, '[^,]+', 1, level) is not null
)
);
VALUE
------------------------------
Beatty,Ian,Larry,Neesha
如果您正在查看表中的多行,这会有点复杂,因为这会混淆 connect-by 语法,但您可以使用非确定性引用来避免循环:
with t42 (id, value) as (
select 1, 'Ian,Beatty,Larry,Neesha,Beatty,Neesha,Ian,Neesha' from dual
union all select 2, 'Mary,Joe,Mary,Frank,Joe' from dual
)
select id, listagg(value, ',') within group (order by value) as value
from (
select distinct id, value from (
select id, regexp_substr(value, '[^,]+', 1, level) as value
from t42
connect by regexp_substr(value, '[^,]+', 1, level) is not null
and id = prior id
and prior dbms_random.value is not null
)
)
group by id;
ID VALUE
---------- ------------------------------
1 Beatty,Ian,Larry,Neesha
2 Frank,Joe,Mary
当然,如果您正确存储关系数据,则没有必要这样做;在列中使用分隔字符串不是一个好主意。