Oracle拆分字符串及排序

一、需求

  表中有1,1.2,1.1.1数据到6.12.222的数据,现需实现根据分隔符“ . ”将其拆分为三段,并进行排序。

二、代码

 

select TID,(substr(tid,instr(tid,'.',1)+1))
  from TEST
 ORDER BY to_number(REGEXP_SUBSTR(tid, '[[:alnum:]]+', 1, 1)) NULLS FIRST,
      to_number(REGEXP_SUBSTR(tid, '[[:alnum:]]+', 1, 2)) NULLS FIRST,
      to_number(REGEXP_SUBSTR(tid, '[[:alnum:]]+', 1, 3)) NULLS FIRST

三、使用的函数

  • substr() 取得字符串中指定起始位置和长度的字符串 substr( string, start_position, [ length ] )
  • instr() instr函数返回要截取的字符串在源字符串中的位置。返回索引
     语法如下:
       instr( string1, string2 [, start_position [, nth_appearance ] ] )
参数含义
string1源字符串,查找此字符串中的数据。
string2目标字符串,需要在string1中查找的字符串,如分隔符。
start_position代表从string1哪个位置开始查找。可选项,默认为1。
nth_appearance代表从第几次出现string2处开始查找。可选项,默认为1。
  • REGEXP_SUBSTR() R延伸SUBSTR函数的功能,搜索一个正则表达式模式字符串。
     语法如下:
       REGEXP_SUBSTR(source_char, pattern [, position [, occurrence [, match_parameter ]]])
参数含义
source_char源字符串,查找此字符串中的数据。
pattern正则表达式。
position从第几个位置开始正则表达式的查找。
occurrence代表从第几个匹配位置开始执行。
match_parameter模式选择,i表示不区分大小写,c表示区分大小写等。

四、执行结果

执行结果


作者:jocy_G
链接:https://www.jianshu.com/p/415aca46b575
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

<think>好的,用户现在问的是在Oracle存储过程中使用WM_CONCAT函数时如何去除重复的字符串。首先,我需要回忆一下WM_CONCAT这个函数的相关知识。记得WM_CONCAT是Oracle的一个非公开函数,用于将多行数据合并成一个字符串,用逗号分隔。不过这个函数在官方文档中并没有正式说明,可能在不同版本中有变化,甚至被移除,比如在12c以后可能需要启用特定兼容性设置才能使用。 接下来,用户的问题是关于在WM_CONCAT中去重。通常,WM_CONCAT本身不会自动去重,所以如果原始数据有重复值,合并后的字符串也会有重复。这时候用户可能遇到需要合并字符串但又不希望重复的情况,比如统计某个字段的不同值。 我需要考虑几种去重的方法。首先,想到的是在WM_CONCAT之前对数据进行去重。比如在子查询中使用DISTINCT或者GROUP BY来确保传递给WM_CONCAT的数据是唯一的。例如: SELECT WM_CONCAT(name) FROM (SELECT DISTINCT name FROM table); 这样应该能合并唯一的名字。不过需要注意,DISTINCT可能会影响性能,尤其是在大数据量的情况下,需要评估执行计划。 另外,如果用户使用的是较新的Oracle版本,比如11g或更高,可能推荐使用LISTAGG函数替代WM_CONCAT,因为LISTAGG是官方支持的,并且功能更稳定。同时,LISTAGG结合DISTINCT可以更方便地实现去重: SELECT LISTAGG(name, ',') WITHIN GROUP (ORDER BY name) FROM (SELECT DISTINCT name FROM table); 这种情况下,用户可能需要修改原有的存储过程,将WM_CONAT替换为LISTAGG,这样既符合官方建议,又能实现去重。 还有一种情况,用户可能因为历史原因必须使用WM_CONCAT,这时可能需要自定义聚合函数或者使用其他方法,比如正则表达式去重。但这种方法比较复杂,可能需要拆分字符串再合并,效率可能不高,尤其是在处理大量数据时。 同时,还要考虑存储过程中的性能问题。如果数据量很大,使用DISTINCT或LISTAGG可能会消耗较多资源,需要评估是否合适,或者是否有其他优化方法,比如临时表存储去重后的数据再进行合并。 另外,用户可能对WM_CONCAT不熟悉,或者遇到版本兼容性问题,需要提醒用户注意函数的可用性,并建议使用官方推荐的替代方案。 总结来说,回答需要涵盖以下几点: 1. 指出WM_CONCAT的非官方性质及可能的替代方案。 2. 在子查询中使用DISTINCT去重后再用WM_CONCAT合并。 3. 推荐使用LISTAGG结合DISTINCT作为更好的解决方案。 4. 提到其他可能的去重方法及注意事项,比如性能、版本兼容性等。 最后,确保回答清晰易懂,并提供示例代码帮助用户理解如何实现。同时,提醒用户在使用非官方函数时的风险,并建议尽可能迁移到官方支持的函数,以保证代码的稳定性和可维护性。</think>在 Oracle 数据库中,`WM_CONCAT` 是一个非公开的内置函数(未在官方文档中正式支持),用于将多行数据合并为单个字符串(类似于 `LISTAGG`)。但 **`WM_CONCAT` 本身不提供去重功能**,如果原始数据中存在重复值,合并后的字符串也会包含重复内容。若要在使用 `WM_CONCAT` 时实现字符串去重,可以通过以下方法实现: --- ### 1. **在子查询中使用 `DISTINCT` 去重** 在调用 `WM_CONCAT` 之前,先通过子查询对数据进行去重,确保传递给 `WM_CONCAT` 的数据是唯一的。 ```sql SELECT WM_CONCAT(name) FROM ( SELECT DISTINCT name FROM your_table WHERE your_conditions ); ``` #### 特点: - 直接利用 `DISTINCT` 消除重复值。 - **性能影响**:若数据量较大,`DISTINCT` 可能导致排序和临时表操作,需注意效率。 --- ### 2. **使用 `LISTAGG` 替代 `WM_CONCAT`(推荐)** `WM_CONCAT` 是 Oracle 的非官方函数,且在高版本(如 12c+)中可能不可用。官方推荐的替代方案是 `LISTAGG`,它支持更规范的语法和去重功能。 ```sql SELECT LISTAGG(name, ',') WITHIN GROUP (ORDER BY name) AS concatenated_names FROM ( SELECT DISTINCT name FROM your_table WHERE your_conditions ); ``` 或直接结合 `DISTINCT`: ```sql SELECT LISTAGG(DISTINCT name, ',') WITHIN GROUP (ORDER BY name) FROM your_table WHERE your_conditions; ``` #### 优势: - 官方支持,语法明确,功能稳定。 - 直接通过 `DISTINCT` 关键字去重,简洁高效。 --- ### 3. **自定义函数去重** 若因兼容性问题必须使用 `WM_CONCAT`,可以通过自定义函数或正则表达式对合并后的字符串去重。例如: ```sql -- 示例:使用正则表达式去重(适用于简单场景) SELECT REGEXP_REPLACE( WM_CONCAT(name), '([^,]+)(,\1)+', '\1' ) AS deduplicated_str FROM your_table; ``` #### 注意: - 正则表达式去重可能复杂且性能较差,尤其是字符串较长时。 - 更可靠的方式仍是先对数据去重,再合并。 --- ### 4. **临时表或 CTE 预处理** 将去重后的数据先存入临时表或公共表表达式(CTE),再调用 `WM_CONCAT`: ```sql WITH dedup_data AS ( SELECT DISTINCT name FROM your_table WHERE your_conditions ) SELECT WM_CONCAT(name) FROM dedup_data; ``` #### 适用场景: - 需要多次引用去重后的数据集时,可提升代码可读性。 --- ### 关键注意事项: 1. **`WM_CONCAT` 的局限性**: - 未在 Oracle 官方文档中明确支持,可能在高版本中被移除。 - 默认以逗号分隔,不支持自定义分隔符(需手动处理)。 - 合并结果长度限制为 4000 字节(与 `VARCHAR2` 类型相关)。 2. **性能优化**: - 若数据量极大,优先使用 `LISTAGG` 并确保索引有效。 - 避免在存储过程中频繁调用 `WM_CONCAT` 或 `LISTAGG`,可考虑分批处理。 3. **版本兼容性**: - 若使用 Oracle 11g 或更高版本,强烈建议迁移到 `LISTAGG`。 --- ### 总结 在存储过程中实现 `WM_CONCAT` 的字符串去重,**最优方案是使用 `LISTAGG(DISTINCT ...)`**。若必须使用 `WM_CONCAT`,则需通过子查询 `DISTINCT` 或预处理数据确保唯一性。同时,始终优先考虑官方支持的函数以保证代码的长期稳定性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值