我有一组包含最少1个和最多3个值的字符串,格式如下:
123;456;789
123;123;456
123;123;123
123;456;456
123;456;123
我正在尝试编写一个正则表达式,因此我可以在同一个字符串上找到重复的值,所以如果你有123;456;789
,它会返回null
,但如果你有123;456;456
它将返回456
并返回123;456;123
返回123
我设法写了这个表达式:
(.*?);?([0-9]+);?(.*?)\2
它的工作原理是,当没有重复值但它没有返回我需要的值时返回null
,例如:对于字符串123;456;456
,它返回123;456;456
}对于字符串123;123;123
,它返回123;123
我需要的是只返回表达式([0-9]+)
部分的值,从我读过的内容通常是使用非捕获组完成的。但要么我做错了要么Oracle SQL不支持这个,好像我尝试使用?:
语法,结果不是我所期望的。
关于如何在oracle sql上进行此操作的任何建议?此表达式的目的是在查询中使用它。
SELECT REGEXP_SUBSTR(column, "expression") FROM DUAL;
编辑:
实际上根据https://docs.oracle.com/cd/B12037_01/appdev.101/b10795/adfns_re.htm
Oracle数据库实现了符合POSIX扩展正则表达式(ERE)规范的正则表达式支持。
根据https://www.regular-expressions.info/refcapture.html
POSIX ERE不支持非捕获组
答案 0 :(得分:1)
如果您只有三个子串,那么您可以使用强力方法。它不是特别漂亮,但它应该做的工作:
select (case when val1 in (val2, val3) then val1
when val2 = val3 then val2
end) as repeated
from (select t.*,
regexp_substr(col, '[^;]+', 1, 1) as val1,
regexp_substr(col, '[^;]+', 1, 2) as val2,
regexp_substr(col, '[^;]+', 1, 3) as val3
from t
) t
where val1 in (val2, val3) or val2 = val3;
答案 1 :(得分:1)
This answer介绍了如何从正则表达式中选择匹配的组。所以使用它,
SELECT regexp_substr(column, '(\d{3}).*\1', 1, 1, NULL, 1) from dual;
# ^ Select group 1
Working demo正则表达式(礼貌:OP)。
答案 2 :(得分:0)
请耐心等待,并考虑这种不同的方法。以稍微不同的方式查看问题并以一种方式对其进行细分,使您可以更灵活地查看数据。它可能适用于您的情况,也可能不适用于您的情况,但希望有趣的是要记住,总有不同的方法可以解决问题。
如果您将字符串转换为行,以便可以针对它们执行标准SQL,该怎么办?这样,您不仅可以计算重复的元素,还可以应用聚合函数来查找集合或其他内容的模式。
然后考虑一下。第一个公用表表达式(CTE)构建原始数据集。第二个,tbl_split,将该数据转换为列表中每个元素的行。取消注释紧随其后的选择以查看。最后一个查询从拆分数据中选择,显示元素在id数据中出现的频率计数。取消注释HAVING行,将输出限制为那些对您所追踪的数据出现多次的元素。
使用行中的数据,您可以看到如何将其他聚合函数应用于切片和切块以显示模式等。
SQL> with tbl_orig(id, str) as (
select 1, '123;456;789' from dual union all
select 2, '123;123;456' from dual union all
select 3, '123;123;123' from dual union all
select 4, '123;456;456' from dual union all
select 5, '123;456;123' from dual
),
tbl_split(id, element) as (
select id,
regexp_substr(str, '(.*?)(;|$)', 1, level, NULL, 1) element
from tbl_orig
connect by level <= regexp_count(str, ';')+1
and prior id = id
and prior sys_guid() is not null
)
--select * from tbl_split;
select distinct id, element, count(element)
from tbl_split
group by id, element
--having count(element) > 1
order by id;
ID ELEMENT COUNT(ELEMENT)
---------- ----------- --------------
1 123 1
1 456 1
1 789 1
2 123 2
2 456 1
3 123 3
4 123 1
4 456 2
5 123 2
5 456 1
10 rows selected.
SQL>