如何通过 Oracle regexp_replace 从空格分隔列表中删除重复项? [复制]
Posted
技术标签:
【中文标题】如何通过 Oracle regexp_replace 从空格分隔列表中删除重复项? [复制]【英文标题】:How to remove duplicates from space separated list by Oracle regexp_replace? [duplicate] 【发布时间】:2017-03-08 15:18:48 【问题描述】:我有一个名为“A B A A C D”的列表。我的预期结果是“A B C D”。到目前为止,我已经从网络上发现了
regexp_replace(l_user ,'([^,]+)(,[ ]*\1)+', '\1');
表达式。但这是用于 , 分隔的列表。为了使其成为空格分隔列表,需要进行哪些修改。无需考虑顺序。
【问题讨论】:
【参考方案1】:如果我理解得很好,您不仅需要用空格替换“,”,还需要以更智能的方式删除重复项。
如果我修改该表达式以使用空格而不是“,”,我会得到
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
)
)
我的主要问题是我无法构建一个检查非相邻重复项的正则表达式,所以我需要拆分字符串,检查重复项,然后再次聚合非重复值,保持顺序。
如果您不介意结果字符串中标记的顺序,可以简化:
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
)
【讨论】:
不用等太久。 :-) 但是,唯一的改进在于外部查询 - 仅使用 rn=1 的行。在这种情况下,这是唯一可能的简化。 @mathguy - 我有种嵌套太多的感觉... :) 仍然在想一些正则表达式组合是否可以避免分裂,但希望不大... 虽然长选择嵌套会很受欢迎。我仍然可以在正确的解决方案上牺牲处理时间。谢谢【参考方案2】:假设您希望将组件字符串保持在它们第一次出现的顺序(而不是按字母顺序重新排序 - 您的示例在这方面选择不当,因为两者都导致相同的结果),问题更多复杂,因为您也必须跟踪订单。然后对于每个字母,您必须只保留第一次出现 - 这是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
;
【讨论】:
订单不是问题。如果 'A B A A C D' 是一个变量,如何将它传递到这里 什么样的变量? (或者您的意思是表中列中的值?)如果它是绑定变量,例如:str
,只要我有列名str
的地方写:str
。注意 - 如果您需要在一个表上执行此操作,并且输入表有不止一行,那么“连接依据”查询会稍微复杂一些。
另外,如果结果字符串中标记的顺序不必与初始字符串相关,那么解决方案可以避免子查询-外部查询结构(以及使用row_number()
) .【参考方案3】:
Xquery?
select xmlquery('string-join(distinct-values(ora:tokenize(.," ")), " ")' passing 'A B A A C D' returning content) result from dual
【讨论】:
在一个系统上需要什么来完成这项工作?我刚刚在我的机器上试了一下,显示的输出是(XMLTYPE)
,而不是A B C D
。
环绕xmlcast( xmlquery(... ) as varchar2(2000))
以上是关于如何通过 Oracle regexp_replace 从空格分隔列表中删除重复项? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
如何通过 Oracle regexp_replace 中的正则表达式从逗号分隔列表中删除重复项? [复制]
如何在 Oracle 中使用 REGEXP_REPLACE 删除单词
如何在 edb 中使用相同的 REGEXP_REPLACE(Oracle sql)