前言:
最新又遇到了一个很久之前做的需求,就是计算流程绩效,比如从前面一个节点收到的时候,流转到下一个流程节点的耗时等。从实现角度看,我们需要两个时间,即上个节点的收到时间、下一个节点的处理时间,然后再计算耗时(如是否超24h/超5天之类的),是不是So,easy!但如果我们需要从一串字符串里面去抓取对应的时间呢?这时候我们该怎么办?
最终效果图1
最终效果图2
一、 一般思路(排除法)
1、数据源分析
首先,正如我们看到的,我们是在一堆流程意见里面去抓取对应的日期,且抓取最初一条的执行时间。
如上图所示,一共是3个流程处理时间,我们需要获取第一个流程处理时间,即2024-07-03 19:06。
2、抓取思路
思考过程:从对应数据来看,我们需要将所有中文、换行、回车等数据去掉,因此,我们会使用到replace函数,或者translate函数来处理。接下来就是找到中文的表达式,我们一般会想到正则表达式,类似[\u4e00-\u9fa5]来去掉字符串中的中文。
对应我已经给你们踩坑了,效果不理想,具体可以参考我以前写的。
oracle 过滤字段中的中文,不再洋不洋土不土_oracle sql去掉字符串中的中文-CSDN博客
代码:
select distinct field0034,regexp_replace(field0034,'[\u4e00-\u9fa5]', '') 中文表达式替换效果
from V3XUSER.formmain_2478 zb
效果:
很显然效果是很不理想的,将数字全替换掉了,而且横杆好像也被认为是汉字了,那我们该怎么办呢?
二、换个思路(匹配法)
1、匹配规则
上面我们排除法显然是想不通了,那我们就正向面对它,只保留,包含数字、横杆、空格、时间冒号的字符不就好了。
2、抓取思路
因此我们只需这样...
代码:
思路:匹配0-9的数字空格、横杆、冒号等,即这关键的一串('0123456789 -:'),然后去前后空格,截取前16为的字符,即可获取对应的日期数据。
select field0034,
substr(trim(translate(field0034,'#'||translate(field0034,'0123456789 -:','#') ,'/') ),1,16) 匹配法1
from V3XUSER.formmain_2478 zb
效果:
从上图来看,效果好似能满足我们的需求了,其实还远远不够,因此当日期意见里面一旦出现前面需要的字符就功亏一篑了。像这样、这样....
三、优化思路(匹配法)
1、问题分析
前面说到的匹配法,其实基本可以解决90%的以上的数据匹配了,但是对于倔强的打工人来说,还是远远不够的。因此当日期前面出现同类的数据,可能就会得到不想要的数据了,因此我们该怎么去匹配呢?去匹配第一个字符是类似2024/2023这种年份的数据,恭喜你,如果你这么去想,那你离成功不远了。
2、优化思路(精确匹配)
前面我们不成功的原因是,我们没有做到精确匹配,因为我们需要获取的最终数据是类似2024-07-03 19:06这种格式的数据。那这种数据有什么共性呢?
不难发现,这些时间数据,由前面的4位数字年份+“-”+2位数字月份+“-”+2位数字的日期+“空格”+2位数字的小时+“:”+2位数字的分钟数。然后根据匹配规则进行截取第一个出现匹配的值,因此我们的正则表达式应该为。\d{4}-\d{2}-\d{2} \d{2}:\d{2}
这里,\d{4}
代表4位数字(年份),\d{2}
代表2位数字(月份、日期、小时、分钟、秒),-
和:
是日期时间格式中的分隔符。注意,这个正则表达式假设日期时间格式是严格固定的,并且只匹配一次出现(即如果字段中有多个日期时间格式,它只会匹配第一个)。
然后对应代码就是长这样,是不是豁然开朗了呀~
代码:
select field0034,REGEXP_SUBSTR(field0034, '\d{4}-\d{2}-\d{2} \d{2}:\d{2}') 匹配法2,
substr(trim(translate(field0034,'#'||translate(field0034,'0123456789 -:','#') ,'/') ),1,16) 匹配法1
from V3XUSER.formmain_2478 zb
效果:
如上图所示,这种方法就能精确的获取到,所需的数据,而且代码也是最精简的,因此我们在日常工作、学习,需要不断尝试,总能柳暗花明~