Sql Oracle:用于复杂案例的regexp
我有一个表,其中一列包含一个字符串,其中的项用分号(;)分隔 我希望根据字符串的模式有选择地将数据传输到新表 例如,它可能看起来像 16、 );;14;30;24;11;13;14;14;10;13;18;15;18;24;13/18;11;;23;12;;19;10;;11;26;;;42;26;38/39;12;;;;;;;11;;;;;;;;;;;;;;; 或 11、 );;11;11;11;11;11;11;11;11;11;11;11;11;11;11;11;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 我不关心分号之间是什么,但我关心哪些位置包含项。例如,如果我只希望第1、第3、第4个位置包含项目,我将允许以下内容 32;;14;18/12;;;;;;;;; 或32;;14;18/12;;;;55;;;;11;;;;;;; 下面这个位置不好,因为第三个位置没有任何值 32;;;18/12;;;;;;;;; 如果regexp对此有效,那么我可以使用Sql Oracle:用于复杂案例的regexp,sql,regex,oracle,Sql,Regex,Oracle,我有一个表,其中一列包含一个字符串,其中的项用分号(;)分隔 我希望根据字符串的模式有选择地将数据传输到新表 例如,它可能看起来像 16、 );;14;30;24;11;13;14;14;10;13;18;15;18;24;13/18;11;;23;12;;19;10;;11;26;;;42;26;38/39;12;;;;;;;11;;;;;;;;;;;;;;; 或 11、 );;11;11;11;11;11;11;11;11;11;11;11;11;11;11;11;;;;;;;;;;;;;;
merge-into
将所需的记录移动到目标表中。如果不能做到这一点,我将不得不用Java处理每条记录,并有选择地将这些记录插入到新表中
源表:
id | StringValue | count
目标表:
id | StringValue | count
我心目中的sql:
merge into you_target_table tt
using ( select StringValue, count
from source_table where REGEXP_LIKE ( StringValue, 'some pattern')
) st
on ( st.StringValue = tt.StringValue and st.count=tt.count )
when not matched then
insert (id, StringValue , count)
values (someseq.nextval, st.value1, st.count)
when matched then
update
set tt.count = tt.count + st.count;
另外,我确信源表中的所有StringValue都是唯一的,所以匹配时
后面的内容并不重要,但由于语法的原因,我认为我必须有一些内容。对于每个位置,您需要放置一个值[^;]+代码>,它匹配任何字符,而不是代码>并至少出现一次,后跟一个代码>。如果您不喜欢某个职位,请输入[^;]*代码>。这几乎与第一个相似,但字符在之前代码>也可以是无。用^
将整个事情锚定到开头
因此,对于您的第一、第三和第四个职位示例,您将获得:
^[^;]+;[^;]*;[^;]+;[^;]+;
在一个如下所示的查询中:
SELECT *
FROM elbat
WHERE regexp_like(nmuloc, '^[^;]+;[^;]*;[^;]+;[^;]+;');
它可以通过将子表达式放入一个组来进一步改进,也就是说,在它们周围放上括号,并使用quantors——组后大括号中的数字。例如,([^;]+;){2}
将匹配两个非空的位置。您的示例将缩短为:
^[^;]+;[^;]*;([^;]+;){2}
虽然答案完全正确,但还有另一个类似但可能更具可读性的解决方案:
SELECT *
FROM elbat
WHERE regexp_substr(nmuloc, '(.*?)(;|$)', 1, 1, '', 1) is not null
AND regexp_substr(nmuloc, '(.*?)(;|$)', 1, 3, '', 1) is not null
AND regexp_substr(nmuloc, '(.*?)(;|$)', 1, 4, '', 1) is not null;
优点:
- 明确说明不应为空的位置编号
- 在任何情况下都有通用模式,因此无需更改正则表达式
- 可以使用任何正则表达式作为分隔符,而不仅仅是单个字符
- 实际上提取项目,所以您可以使用任何函数对其进行进一步测试
缺点:
- 相当冗长
- 慢n倍,其中n是条件计数
- 更慢(最多2倍)的原因是每个非分隔符符号上的回溯
然而,根据我的经验,如果查询不是针对数十亿行运行的,那么这种效率差异是很小的。即使这样,磁盘读取也会占用大部分时间
制作方法:
- (.*)(;|$)-惰性地搜索以分隔符或字符串结尾的任何字符序列(可能为零长度)
- 1-开始搜索的位置。1是默认值。只需要进入下一个参数
- 1、3或4-事件或模式
- ''-匹配_参数。可用于设置匹配模式,但此处也仅用于获取最后一个参数
- 1-子表达式编号使regexp\u substr仅返回第一个捕获组。即(.*),即项目本身没有分隔符