[英]Oracle multiple replace
我在 Oracle 表中有未清理且一致的保修优惠列。 例如,在这个表中我们有以下数据,我只想保持最高保修期以月为单位(如果不是以月为单位,我想转换它)。 例如,从下面的第一个记录来看,18 个月是最高的,我想将数据保存在几个月内,因此“warranty_offrs”将为“18”,记录 #2 将是“12”而不是 12,记录 #6 将是“24”,值将是 integer 编号:
warranty_offrs (char 2000 字节):
数据有时在数月/天/周括号后带有点(因为它来自不同的来源),以及上面的各种组合。 我在存储过程中这样做,首先尝试使用替换来获取所有“(”“)”“[”“]”“{”“}”但仍然翻译。
我怎样才能实现它,请告诉我?
步骤 2-8 中使用的全局临时表仅包含相关列。
使用 REPLACE 命令从列中删除各种不相关的字符串,例如括号、点等,并将数据加载到 perm 表中。 一些列被转换为小写字母,以便以后计算。 此表包含所有列。
然后我使用您的 pivot 代码将 pivot 字符串值放入行中,例如,warranty_offrs 值“一个月,2 年,3 天”将变为 3 条记录,我将其加载到另一个标记为 {table_name_US_ENG} 的全局临时表中(因为存在相同的列在西班牙语中也是如此,有时它被填充,如果它被填充,那么我需要使用该列中的值)。
对西班牙列重复第 2 步,并在西班牙列有值时将仅透视的记录加载到全局临时 {table_name_ESP} 中。
创建的查找表有两列:单词、数字列,例如“一”、“1”、“十”、“10”等。这将有助于在步骤 5 中将单词转换为数字
来自第 2 步的数据和第 3 步表对第 4 步中的查找执行查找,并获取单词的数值。 “1”代表“一”,“10”代表“十”。 为了保持时间段(年/月等),我使用 substr 将两个值连接回来。 现在我所有的数值都是数字并且有期限(年/天)。 此数据被加载到另一个全局临时表中(将重复西班牙列值到单独的表)。
下一步是将它们转换为月份。 由于这些可能性很少,我使用 case 语句并将它们转换为月份,并加载到另一个全局临时表中(此步骤将针对西班牙数据重复)
然后我执行以下操作以从 us_eng GTT 表中获取 us_eng 列的最大月份:select id, max(mth_us_eng) keep (dense_rank first order by id)max_mth from gtt_table_us_eng。 然后将结果插入到全局临时表中。 (此 sql 对带有西班牙列的全局临时表重复以获得最大月份)
左外连接英语(左表)和西班牙语(右)表,并且只获取匹配插入到最后一个全局临时表的记录(呸!)
现在使用步骤 1 中的 perm 表和步骤 8 中的全局临时表执行 INNER JOIN,并将结果加载到最终 perm 表中。
问题:我们如何将数字与字符串分开? 在某些情况下,列值没有单个空格,而是像“18months”而不是“18months”。
注释:
欢迎任何调整代码的建议。 :)
很难调试你看不到的代码。 你说你写了一个存储过程,但它没有做你想要的。
更换支架很简单; 您可以使用嵌套的REPLACE
(可以完成这项工作,但难以阅读和维护)或 - 更好的选择 - 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>
您的问题的 rest 的一个:看起来该过程会很长,因为您必须涵盖许多不同的情况。 Go 循序渐进,经常测试。 我认为没有魔杖解决方案。
您(在评论中)询问您是否可以解析这些字符串。 是的; 因为它的每个部分都用逗号分隔,所以你会
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>
然后决定如何处理这些值。 正如我之前所说,你有单词和数字的组合,单数和复数,诸如此类 - go 一步一步改变你必须做的。 然后将最终结果合并回来,使用LISTAGG
function。
如果您一次处理不止一行,那么您会得到很多重复的行。 在这种情况下,应相应地调整先前的查询。 下面是方法(我包括了额外的id
列来显示哪个val
属于哪一行):
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>
[编辑,26.03.2021]
如果要在数字后面添加一个空格(如果它不存在,例如将18 months
修改为18months
),则:
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>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.