如何从Oracle regexp_replace中删除空格分隔列表中的重复项?

时间:2016-10-26 09:59:36

标签: sql regex oracle

我有一个名为'A B A A C D'的清单。我的预期结果是'A B C D'。到目前为止,我发现了

regexp_replace(l_user ,'([^,]+)(,[ ]*\1)+', '\1');

表达。但这是分开的列表。需要进行哪些修改才能使其成为空格分隔列表。无需考虑订单。

3 个答案:

答案 0 :(得分:4)

如果我理解得很好,你不仅需要用空格替换',',而且还要以更聪明的方式删除重复项。

如果我修改该表达式以使用空格而不是',',我得到

select regexp_replace('A B A A C D' ,'([^ ]+)( [ ]*\1)+', '\1') from dual

给出了'A B A C D',而不是你需要的。

获得所需结果的方法可能如下,有点复杂:

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
                )
         )

我的主要问题是我无法构建一个检查非相邻重复项的正则表达式,所以我需要拆分字符串,检查重复项,然后再次聚合非重复值,保持顺序。 / p>

如果您不介意结果字符串中令牌的顺序,可以简化:

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
     )

答案 1 :(得分:4)

假设你想要按照第一次出现的顺序保留组件字符串(而不是按照字母顺序对它们进行重新排序 - 在这方面你的例子选择不当,因为两者都导致相同的结果),问题更多很复杂,因为你也必须跟踪秩序。然后对于每个字母,您必须保留第一次出现 - 这里是row_number()帮助的地方。

with
     inputs ( str ) as ( select 'A B A A C D' from dual)
-- end test data; solution begins below this line
select listagg(token, ' ') within group (order by id) as new_str
from (
       select level as id, regexp_substr(str, '[^ ]+', 1, level) as token,
              row_number() over ( 
                             partition by regexp_substr(str, '[^ ]+', 1, level)
                             order by level ) as rn

       from   inputs
       connect by regexp_substr(str, '[^ ]+', 1, level) is not null
     )
where rn = 1
;

答案 2 :(得分:3)

的Xquery?

select xmlquery('string-join(distinct-values(ora:tokenize(.," ")), " ")' passing  'A B A A C D' returning content) result  from dual