Sql Oracle多重替换

Sql Oracle多重替换,sql,oracle,replace,Sql,Oracle,Replace,我在Oracle表中有一列未清理且不一致的保修服务。例如, 在这个表中,我们有以下数据,我只想保持最高的保修期,以月为单位(如果不是以月为单位,我想转换它)。例如,从下面的第一条记录来看,18个月是最高的,我希望以月为单位保存数据,因此“保修费”将为“18”,记录#2将为“12”,而不是12,记录#6将为“24”,值将为整数: 保修主任(字符2000字节): 记录#1:“一年18个月24周” 记录2:“12个月,8个月,60天。” 记录#3:“(30)个月。” 记录#4:“(60)个月,20周。

我在Oracle表中有一列未清理且不一致的保修服务。例如, 在这个表中,我们有以下数据,我只想保持最高的保修期,以月为单位(如果不是以月为单位,我想转换它)。例如,从下面的第一条记录来看,18个月是最高的,我希望以月为单位保存数据,因此“保修费”将为“18”,记录#2将为“12”,而不是12,记录#6将为“24”,值将为整数:

保修主任(字符2000字节):

  • 记录#1:“一年18个月24周”
  • 记录2:“12个月,8个月,60天。”
  • 记录#3:“(30)个月。”
  • 记录#4:“(60)个月,20周。”
  • 记录#5:“1年12个月18个月3年1个月”
  • 记录#6:“{12}周,{2}年,一个月,十二个月。”
  • 数据有时会在月/日/周后的括号中加上点和数字(因为它来自不同的来源),以及上述各种组合。我是在存储过程中这样做的,首先尝试使用replace来处理所有的“(”“)”“[”“]”“{”“}”,但仍然保留了翻译


    如何实现它,请让我知道?

    调试看不到的代码很困难。您说过您编写了一个存储过程,但它并不是您想要的

    更换支架很简单;您可以使用嵌套的
    REPLACE
    s(它可以完成任务,但很难阅读和维护)或-更好的选项-
    TRANSLATE

    SQL> with test (wo) as
      2    (select '(60) months, [20] weeks.' from dual union all
      3     select '{12} weeks, {2} years' from dual
      4    )
      5  select replace(replace(replace(replace(replace(replace(
      6           wo, '(', ''), ')', ''), '[', ''), ']', ''), '{', ''), '}', '') result_1,
      7         --
      8         translate(wo, 'a()[]{}', 'a') result_2
      9  from test;
    
    RESULT_1                 RESULT_2
    ------------------------ ------------------------
    60 months, 20 weeks.     60 months, 20 weeks.
    12 weeks, 2 years        12 weeks, 2 years
    
    SQL>
    
    你的其他问题:看起来这个过程会很长,因为你要处理很多不同的案例。循序渐进,经常测试。我不认为有魔杖解决办法


    您(在评论中)询问是否可以解析这些字符串。对由于它的每一部分都用逗号隔开,因此您可以

    SQL> with test (col) as
      2    (select '1 year, 12 months, 18 months, 3 years, one month' from dual)
      3  select trim(regexp_substr(col, '[^,]+', 1, level)) val
      4  from test
      5  connect by level <= regexp_count(col, ',') + 1;
    
    VAL
    ------------------------------------------------
    1 year
    12 months
    18 months
    3 years
    one month
    
    SQL>
    

    [编辑,2021年3月26日]

    如果要在数字后面添加空格(如果不存在,例如将
    18个月
    修改为
    18个月
    ),则:


    步骤2-8中使用的全局临时表仅包含相关列

  • 使用REPLACE命令从列中删除各种不相关的字符串,例如括号、点等,并将数据加载到perm表中。为了便于以后的计算,一些列被转换为小写字母。此表包含所有列

  • 然后,我使用pivot代码将字符串值透视到行中,例如,保修offrs值“一个月、2年、3天”将成为3条记录,我将其加载到另一个标记为{table_name_US_ENG}的全局临时表中(因为西班牙语中也存在相同的列,有时会填充,如果填充了,则需要使用该列中的值)

  • 对西班牙语列重复步骤2,并在西班牙语列具有值时将仅数据透视记录加载到全局temp{table_name_ESP}

  • 创建的查找表有两列:单词、数字列,例如“一”、“1”、“十”、“10”等。这将有助于在步骤5中将单词转换为数字

  • 步骤2和步骤3表格中的数据在步骤4的查找中执行查找,并获取单词的数值。“1”表示“1”,10表示“10”。为了保留期间(年/月等),我使用substr将两个值重新合并。现在,我所有的数值都以数字表示,并具有期间(年/日)。此数据将加载到另一个全局临时表格中(西班牙语列的值将重复到单独的表中)

  • 下一步是将它们转换为月份。由于这些可能性非常少,我使用case语句将它们转换为月份,并加载到另一个全局临时表中(这一步将对西班牙语数据重复)

  • 然后,我执行以下操作,从us_eng GTT表中获取us_eng的max month列: 从gtt_表_us_eng中选择id,max(mth_us_eng)keep(densite_rank first order by id)max_mth。然后将结果插入全局临时表。 (对于具有西班牙语列的全局临时表,重复此sql以获取最大月数)

  • 左外部将英语(左表)与西班牙语(右表)连接起来,只在最后一个全局临时表(phew!)中插入匹配项的地方获取记录

  • 现在,使用步骤1中的perm表和步骤8中的全局临时表执行内部联接,并将结果加载到最终的perm表中

  • 问题: 如何将数字和字符串分开?在某些情况下,列值没有单个空格,而是类似于“18个月”,而不是“18个月”

    评论:

    • 步骤1中的替换函数比我邻居枫树中的分支要多
    • 我希望我使用GTT不会加剧全球变暖!(尽管我试图把12个月的时间搞糟到24个月)
    • 希望,西班牙语列查找值能提高我下次访问墨西哥时的对话技巧

    欢迎任何修改代码的建议。:/p>我刚刚开始,所以我只有存储过程名称,并选择语句以删除括号。我只想保留最长的持续时间,如在结果中记录的“60个月”和“2年”。我相信只有将所有持续时间转换为月份后,这才可能实现。是否有方法遍历可以包含一个或多个逗号或不包含逗号的列字符串?为此列假设以下值=“一个月、一年、两年、12个月”。我是否可以遍历字符串并在转换后将年/年/年的任何实例替换为月?因此,一年将变为“24个月”,然后我可以再次搜索列中的最高值以仅保留最高值?嗯,“一年”应变为“12个月”(而不是“24个月”),至少在我住的地方。你能做你描述的吗?当然,那叫解析。我在答案的末尾添加了一些信息;看一看。谢谢你的帮助。这看起来像是基于列值中逗号数的水平轴。下面是
    SQL> with test (id, col) as
      2    (select 1, '1 year, 12 months, 18 months, 3 years, one month' from dual union all
      3     select 2, 'twelve months, 8 months, 60 days.' from dual
      4    )
      5  select id,
      6         trim(regexp_substr(col, '[^,]+', 1, column_value)) val
      7  from test cross join
      8    table(cast(multiset(select level from dual
      9                        connect by level <= regexp_count(col, ',') + 1
     10                       ) as sys.odcinumberlist))
     11  order by id, column_value;
    
            ID VAL
    ---------- ------------------------------------------------
             1 1 year
             1 12 months
             1 18 months
             1 3 years
             1 one month
             2 twelve months
             2 8 months
             2 60 days.
    
    8 rows selected.
    
    SQL>
    
    SQL> with
      2  test (col) as
      3    (select 'one year, 18months, 24 weeks' from dual),
      4  temp as
      5    -- split it to rows (you already know how to do that)
      6    (select trim(regexp_substr(col, '[^,]+', 1, level)) val
      7     from test
      8     connect by level <= regexp_count(col, ',') + 1
      9    )
     10  -- in CASE, check whether VAL contains a space. If so, return VAL. If not,
     11  -- add a space after digits
     12  select
     13    val,
     14    case when instr(val, ' ') = 0 then regexp_replace(val, '(\d+)', '\1 ')
     15         else val
     16    end new_val
     17  from temp;
    
    VAL        NEW_VAL
    ---------- ----------
    one year   one year
    18months   18 months
    24 weeks   24 weeks
    
    SQL>
    
    SQL> with test (col) as
      2    (select   1 from dual union all
      3     select  18 from dual union all
      4     select  24 from dual union all
      5     select 673 from dual
      6    )
      7  select col,
      8         to_char(to_date(col, 'j'),'jsp') in_words
      9  from test;
    
           COL IN_WORDS
    ---------- ---------------------------------------------------
             1 one
            18 eighteen
            24 twenty-four
           673 six hundred seventy-three
    
    SQL>