我有一张桌子,其中一列包含一个字符串,其中各项之间用分号(;)隔开
我想根据字符串的模式有选择地将数据传输到新表中。
例如,它可能看起来像
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; 11 ;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;
我不在乎分号之间是什么,但是我在乎哪些位置包含项目。例如,如果我只希望第一,第三,第四位置包含项目,则允许以下内容...
32 ;; 14; 18/12 ;;;;;;;;;或32 ;; 14; 18/12 ;;;; 55 ;;;; 11 ;;;;;;;
下面的那一个不好,因为第三位置没有任何值。
32 ;;; 18/12 ;;;;;;;;
如果正则表达式可以解决这个问题,那么我可以使用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都是唯一的,因此when matched then
之后的内容并不重要,但是由于语法的原因,我认为我必须有一些东西。
答案 0 :(得分:3)
对于每个位置,您需要一个值[^;]+;
,该值匹配任何字符,不是;
,并且至少出现一次,后跟一个;
。如果您不在乎职位,请放[^;]*;
。这几乎与第一个相似,但是;
之前的字符也可能没有。将整个内容以^
开头固定。
因此,对于您的第一,第三和第四位置示例,您将获得:
^[^;]+;[^;]*;[^;]+;[^;]+;
在如下查询中:
SELECT *
FROM elbat
WHERE regexp_like(nmuloc, '^[^;]+;[^;]*;[^;]+;[^;]+;');
通过将子表达式放在一组中,也就是在它们之间加上括号,并使用量化器(该组后面的花括号中的数字)可能会进一步改进。例如,([^;]+;){2}
将匹配两个不为空的位置。您的示例将简化为:
^[^;]+;[^;]*;([^;]+;){2}
答案 1 :(得分:0)
虽然@stiky bit的答案是完全正确的,但还有另一种类似但也许更具可读性的解决方案:
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;
优点:
缺点:
但是,根据我的经验,如果不对数十亿行进行查询,则效率差异很小。即使这样,磁盘读取仍会消耗大部分时间。
如何制作: