我想使用oracle从逗号分隔的sting中删除特定值。
示例输入 -
col
1,2,3,4,5
假设我想从字符串中删除3。
示例输出 -
col
1,2,4,5
请使用oracle查询建议我如何做到这一点。
感谢。
答案 0 :(得分:4)
这是一个只使用标准字符串函数(而不是正则表达式)的解决方案 - 在大多数情况下应该可以更快地执行;只有当第一个字符后跟逗号,最后一个字符前面有逗号,或者前面跟着逗号后才删除3,并删除中间情况下它前面的逗号,并删除后面的逗号。第一和第三种情况。
它可以连续删除两个3(其他一些解决方案无法提供),同时留下连续的逗号(可能代表NULL)并且不会干扰38或123之类的数字
策略是首先将每个逗号加倍(用,
替换,,
)并附加并添加逗号(到字符串的开头和结尾)。然后删除,3,
的每次出现。从剩下的内容中,将每个,,
替换为一个,
,最后删除前导和尾随,
。
with
test_data ( str ) as (
select '1,2,3,4,5' from dual union all
select '1,2,3,3,4,4,5' from dual union all
select '12,34,5' from dual union all
select '1,,,3,3,3,4' from dual
)
select str,
trim(both ',' from
replace( replace(',' || replace(str, ',', ',,') || ',', ',3,'), ',,', ',')
) as new_str
from test_data
;
STR NEW_STR
------------- ----------
1,2,3,4,5 1,2,4,5
1,2,3,3,4,4,5 1,2,4,4,5
12,34,5 12,34,5
1,,,3,3,3,4 1,,,4
4 rows selected.
注意正如MT0所指出的(参见下面的评论),如果原始字符串以逗号开头或结尾,这将修剪得太多。为了覆盖这种情况,我应该将其余内容包装在子查询中,而不是将所有内容包装在子查询中,并在外部查询中使用类似trim(both ',' from ...)
的内容。
答案 1 :(得分:3)
这是一种方法:
select trim(both ',' from replace(',' || '1,2,3,4,5' || ',', ',' || '3' || ',', ','))
也就是说,存储以逗号分隔的字符串是一个非常非常糟糕的主意。几乎没有理由做这样的事情。 Oracle支持JSON,XML和嵌套表 - 所有这些都是更好的选择。
删除元素的需要表明数据设计不佳。
答案 2 :(得分:1)
您可以使用XMLTABLE
转换列表行,过滤以删除不需要的行,然后重新聚合它们:
SELECT LISTAGG( x.value.getStringVal(), ',' ) WITHIN GROUP ( ORDER BY idx )
FROM XMLTABLE(
( '1,2,3,4,5' )
COLUMNS value XMLTYPE PATH '.',
idx FOR ORDINALITY
) x
WHERE x.value.getStringVal() != 3;
对于一个简单的过滤器,这可能不值得,你应该使用类似的东西(基于@ mathguy的solution):
SELECT SUBSTR( new_list, 2, LENGTH( new_list ) - 2 ) AS new_list
FROM (
SELECT REPLACE(
REPLACE(
',' || REPLACE( :list, ',', ',,' ) || ',',
',' || :value_to_replace || ','
),
',,',
','
) AS new_list
FROM DUAL
)
但是,如果过滤更复杂,那么将列表转换为行,过滤和重新聚合可能是值得的。
答案 3 :(得分:0)
我不知道如何在Oracle中执行此操作,但使用SQL-Server我会使用一个技巧:
XQuery
过滤数据这是SQL Server语法,但可能指向您的方向:
declare @s varchar(100)='1,2,2,3,3,4';
declare @exclude int=3;
WITH Casted AS
(
SELECT CAST('<x>' + REPLACE(@s,',','</x><x>') + '</x>' AS XML) AS TheXml
)
SELECT x.value('.','int')
FROM Casted
CROSS APPLY TheXml.nodes('/x[text()!=sql:variable("@exclude")]') AS A(x)
I just found this answer似乎很好地展示了如何开始......
答案 4 :(得分:0)
我同意Gordon的观点,即在列中存储逗号分隔的数据是一个非常糟糕的主意。
我只是在csv之前加上&#39;&#39;,然后使用替换功能,然后使用左侧修剪功能来清理前面的&#39;,&#39;。
SCOTT@tst>VAR b_number varchar2(5);
SCOTT@tst>EXEC :b_number:= '3';
PL/SQL procedure successfully completed.
SCOTT@tst>WITH srce AS (
2 SELECT
3 ',' || '3,1,2,3,3,4,5,3' col
4 FROM
5 dual
6 ) SELECT
7 ltrim(replace(col,',' ||:b_number),',') col
8 FROM
9 srce;
COL
1,2,4,5