用多字符替换字符串中的每个字符

时间:2019-10-06 18:47:30

标签: sql oracle

我需要将值“ 123”替换为JANFEBMAR。 像这样: 1替换为JAN,2替换为FEB ...等。

我这样写 select replace(replace(replace(replace('1234','1','JAN'),'2','FEB'),'3','MAR'),'4','APR') from dual; 这看起来不干净,并且可能也会影响性能。如何通过REGEXP_REPLACE实现?

4 个答案:

答案 0 :(得分:0)

这里是一个选择:

SQL> with test (col) as
  2    (select '159' from dual),
  3  mon as
  4    (select to_char(to_date(lpad(regexp_substr(col, '\d', 1, level), 2, '0'), 'mm'), 'mon') val,
  5            level lvl
  6     from test
  7     connect by level <= length(col)
  8    )
  9  select listagg(val, '') within group (order by lvl) result
 10  from mon;

RESULT
--------------------------------------------------------------------------------
janmaysep

SQL>

尽管如此,您的问题有点奇怪;您想将1312转换成什么?是janmarjanfeb还是janmardec

答案 1 :(得分:0)

您仍可以将regexp_replace与包含to_date的{​​{1}}函数和包含MM作为第二个参数的to_char函数一起使用:

MON

Demo

顺便说一句,您可以将文字'123'转换为所需的任何内容,例如'234','342','4587'并在演示中进行测试。 在当前情况下,只要您在 1月(1) 9月(9)之间需要几个月的时间,该方法就可以使用。

答案 2 :(得分:0)

尝试拆分字符串然后将其转换为月份名称是有问题的,原因如下:

  1. 假设您的值为1212。无法知道这是否对应于DecDecJanFebDecDecJanFebJanFebJanFeb
  2. 您的字符串长度是可变的,因为有些月份是2位数字,有些月份是1位数字。
  3. 试图撕裂并转换一列字符串(或表示字符串值的整数)本质上是糟糕的数据管理。容易出现破损,错误和昂贵的低效率查询。在尝试使用其他解决方案之前,先尝试一下。

首先要问自己的问题: 该数据如何首先加载到表中?

以某种方式查找一个月的整数表示形式,然后将其与其他月份连接起来。为什么不将其转换为月份名称而不是整数,然后才将其转换为该表?

问自己的第二个问题: 该数据的下一步是什么?

诸如“ JanFebMar”和“ MarFebSep”之类的字符串不是特别灵活,可读性强或对许多有用。很有可能,您稍后必须在工作流程中转换或拆分这些字符串,以使其变得有用。

我强烈建议像这样重组表:

Columns_with_your_other_data | MONTH1 | MONTH2 | MONTH3

这使您可以使月份保持井然有序,将它们转换为整数或字符串,对其进行连接或拆分,对它们进行排序,对它们进行过滤,无论您想要什么,都可以避免错误和对数据库造成额外压力。方式更灵活!不太容易出错。方式更具可读性。一种更好的方式来管理数据。

如果您在任何情况下都绝对无法重组表(这似乎不太可能),则至少需要将整数月份值重新格式化为两位数而不是一位数(即Jan = 01,而不是1),以避免解析错误的月份。

答案 3 :(得分:0)

Oracle设置

CREATE TABLE test_data ( value ) AS
  SELECT '1234' FROM DUAL UNION ALL
  SELECT '1212' FROM DUAL UNION ALL
  SELECT '123456789101112' FROM DUAL UNION ALL
  SELECT '1 23456789101112' FROM DUAL UNION ALL
  SELECT '12AA34' FROM DUAL

查询1

最有效的解决方案是嵌套REPLACE语句,并且,除非您有大量替换用语,否则它将是最简单的检查方式(如果您对代码进行整洁的格式化):

SELECT value,
       REPLACE(
         REPLACE(
           REPLACE(
             REPLACE(
               REPLACE(
                 REPLACE(
                   REPLACE(
                     REPLACE(
                       REPLACE(
                         REPLACE(
                           REPLACE(
                             REPLACE(
                               value, '12', 'DEC'
                             ),
                             '11', 'NOV'
                           ),
                           '10', 'OCT'
                         ),
                         '9', 'SEP'
                       ),
                       '8', 'AUG'
                     ),
                     '7', 'JUL'
                   ),
                   '6', 'JUN'
                 ),
                 '5', 'MAY'
               ),
               '4', 'APR'
             ),
             '3', 'MAR'
           ),
           '2', 'FEB'
         ),
         '1', 'JAN'
       ) AS replaced_value
FROM   test_data;

输出

VALUE            | REPLACED_VALUE                       
:--------------- | :------------------------------------
1234             | DECMARAPR                            
1212             | DECDEC                               
123456789101112  | DECMARAPRMAYJUNJULAUGSEPOCTNOVDEC    
1 23456789101112 | JAN FEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC
12AA34           | DECAAMARAPR                          

查询2

如果要遍历值,则可以构建一个递归查询(甚至处理非数字替换):

WITH replacements ( item, replacement ) AS (
  SELECT  '1', 'JAN' FROM DUAL UNION ALL
  SELECT  '2', 'FEB' FROM DUAL UNION ALL
  SELECT  '3', 'MAR' FROM DUAL UNION ALL
  SELECT  '4', 'APR' FROM DUAL UNION ALL
  SELECT  '5', 'MAY' FROM DUAL UNION ALL
  SELECT  '6', 'JUN' FROM DUAL UNION ALL
  SELECT  '7', 'JUL' FROM DUAL UNION ALL
  SELECT  '8', 'AUG' FROM DUAL UNION ALL
  SELECT  '9', 'SEP' FROM DUAL UNION ALL
  SELECT '10', 'OCT' FROM DUAL UNION ALL
  SELECT '11', 'NOV' FROM DUAL UNION ALL
  SELECT '12', 'DEC' FROM DUAL UNION ALL
  SELECT 'AA', '???' FROM DUAL
),
list ( item, replacement, next_item, max_item ) AS (
  SELECT item,
         replacement,
         LAG( item ) OVER ( ORDER BY LENGTH( item ) ASC, item ASC ),
         MAX( item ) KEEP ( DENSE_RANK LAST ORDER BY LENGTH( item ), item ASC ) OVER ()
  FROM   replacements
),
replaced_values ( value, item ) AS (
  SELECT REPLACE( value, item, replacement ), next_item
  FROM   test_data
         CROSS JOIN
         list
  WHERE  item = max_item
UNION ALL
  SELECT REPLACE( value, r.item, replacement ), next_item
  FROM   replaced_values r
         INNER JOIN list l
         ON ( r.item = l.item )
  WHERE  r.item IS NOT NULL
)
SELECT value
FROM   replaced_values
WHERE  item IS NULL;

输出

| VALUE                                 |
| :------------------------------------ |
| DECMARAPR                             |
| DECDEC                                |
| DECMARAPRMAYJUNJULAUGSEPOCTNOVDEC     |
| JAN FEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC |
| DEC???MARAPR                          |

db <>提琴here