使用 Oracle Query 显示所有匹配的记录
Posted
技术标签:
【中文标题】使用 Oracle Query 显示所有匹配的记录【英文标题】:Display all matched records using Oracle Query 【发布时间】:2021-10-04 12:10:45 【问题描述】:我在 Oracle 中使用 Connect by Level 查询以显示所有匹配的记录 regexp_substr 但它没有显示全部,我需要将 Connect by Level 从 +1 更改为 +8 以获得所有结果。如果未来的比赛比这更多怎么办?我想在不将 +1 更改为 +10 或 +20 等的情况下捕获多少匹配项。有没有最简单和最快的方法?
这是我的查询:
SELECT DATA_SOURCE,REGEXP_SUBSTR(DATA_SOURCE,'A-\S+|ABC\S+',1, LEVEL) AS REF_NUM
FROM
(
SELECT '
Z-TEST
Y-TEST
A-123456789
ABC123456790
Y-TRY
A-123456791
ABC123456792
ABC123456793
Y-TRY
Y-TRY
Z-TEST
Y-TEST
Z-TEST
Y-TEST
A-123456794
ABC123456795
ABC123456796
Y-TRY
Z-TEST
Y-TEST
Z-TEST
Y-TEST
A-123456797
ABC123456798
' DATA_SOURCE
FROM DUAL
)
CONNECT BY LEVEL <= LENGTH(REGEXP_COUNT(DATA_SOURCE,'A-\S+|ABC\S+'))+1
Result:
A-123456789
ABC123456790
A-123456791
Desired Result:
REF_NUM
A-123456789
ABC123456790
A-123456791
ABC123456792
ABC123456793
A-123456794
ABC123456795
ABC123456796
A-123456797
ABC123456798
【问题讨论】:
你为什么要比较计数的长度?如果输出中有 8 个结果,则计数为 8。8 的长度为 1。(“长度”表示数字中有多少位 - 在本例中为一位。)为什么要将任何内容与 1 进行比较,而不是 8? 除此之外,你确定你的正则表达式是正确的吗?如果输入包含字符串DMA-123
,它也会返回A-123
,这是你需要的吗?
嗨@mathguy,你是对的,应该修改正则表达式,我只需要那些第一个字符串'^A-|^ABC',1,1,'m' 我在Connect中尝试了多行函数按级别不起作用!有什么建议吗?
【参考方案1】:
你的 connect by 子句应该是
CONNECT BY LEVEL <= REGEXP_COUNT(DATA_SOURCE,'A-\S+|ABC\S+', 1)
而不是
CONNECT BY LEVEL <= LENGTH(REGEXP_COUNT(DATA_SOURCE,'A-\S+|ABC\S+'))+1
但如果您想将此解决方案应用于具有更多行的表,则需要添加以下内容:
CONNECT BY LEVEL <= REGEXP_COUNT(DATA_SOURCE,'A-\S+|ABC\S+', 1)
AND PRIOR DATA_SOURCE = DATA_SOURCE
AND PRIOR SYS_GUID() IS NOT NULL
到您的 connect by 子句。
所以你的查询最终应该是这样的:
SELECT --DATA_SOURCE,
REGEXP_SUBSTR(DATA_SOURCE,'A-\S+|ABC\S+',1, LEVEL) AS REF_NUM
FROM
(
SELECT '
Z-TEST
Y-TEST
A-123456789
ABC123456790
Y-TRY
A-123456791
ABC123456792
ABC123456793
Y-TRY
Y-TRY
Z-TEST
Y-TEST
Z-TEST
Y-TEST
A-123456794
ABC123456795
ABC123456796
Y-TRY
Z-TEST
Y-TEST
Z-TEST
Y-TEST
A-123456797
ABC123456798
' DATA_SOURCE
FROM DUAL
)
CONNECT BY LEVEL <= REGEXP_COUNT(DATA_SOURCE,'A-\S+|ABC\S+', 1)
AND PRIOR DATA_SOURCE = DATA_SOURCE
AND PRIOR SYS_GUID() IS NOT NULL
;
demo
For further explanation
【讨论】:
嗨@MDBIA,即使您的查询有多个匹配项,结果也只有一个...... 我不确定我是否得到了你的帮助,但我在我的答案中添加了一个演示链接。你可以在那里测试它。 嗨@MDBIA 我看到了演示,是的,它按我想要的方式工作,我会检查实际查询并告诉你。 嗨@ClintMohamed,我更新了我的答案以涵盖多行案例。希望这会有所帮助。 嗨@MDBIA,非常感谢。【参考方案2】:将按条件连接更改为例如CHR(13)
出现次数(第 35 行),然后选择存在 ref_num
的行(第 38 行)。像这样的:
SQL> WITH
2 temp
3 AS
4 ( SELECT DATA_SOURCE,
5 REGEXP_SUBSTR (DATA_SOURCE,
6 'A-\S+|ABC\S+',
7 1,
8 LEVEL) AS REF_NUM
9 FROM (SELECT '
10 Z-TEST
11 Y-TEST
12 A-123456789
13 ABC123456790
14 Y-TRY
15 A-123456791
16 ABC123456792
17 ABC123456793
18 Y-TRY
19 Y-TRY
20 Z-TEST
21 Y-TEST
22 Z-TEST
23 Y-TEST
24 A-123456794
25 ABC123456795
26 ABC123456796
27 Y-TRY
28 Z-TEST
29 Y-TEST
30 Z-TEST
31 Y-TEST
32 A-123456797
33 ABC123456798
34 ' DATA_SOURCE FROM DUAL)
35 CONNECT BY LEVEL <= REGEXP_COUNT (data_source, CHR (10)))
36 SELECT ref_num
37 FROM temp
38 WHERE ref_num IS NOT NULL;
REF_NUM
--------------------
A-123456789
ABC123456790
A-123456791
ABC123456792
ABC123456793
A-123456794
ABC123456795
ABC123456796
A-123456797
ABC123456798
10 rows selected.
SQL>
[EDIT] 如果您实际上是一次解析表格内容(不是一个 huge 字符串),那么看看这样的示例是否有帮助。我将您的示例数据分成两行并添加了ID
列(只是为了更轻松地查看结果)。
SQL> with your_table (id, data_source) as
2 (select 1, '
3 Z-TEST
4 Y-TEST
5 A-123456789
6 ABC123456790
7 Y-TRY
8 A-123456791
9 ABC123456792
10 ABC123456793
11 Y-TRY
12 Y-TRY
13 ' from dual
14 union all
15 select 2, '
16 Z-TEST
17 Y-TEST
18 Z-TEST
19 Y-TEST
20 A-123456794
21 ABC123456795
22 ABC123456796
23 Y-TRY
24 Z-TEST
25 Y-TEST
26 Z-TEST
27 Y-TEST
28 A-123456797
29 ABC123456798
30 ' from dual
31 )
32 select id,
33 regexp_substr (data_source, 'A-\S+|ABC\S+', 1, column_value) as ref_num
34 from your_table cross join
35 table(cast(multiset(select level from dual
36 connect by level <= regexp_count (data_source, chr (10))
37 ) as sys.odcinumberlist))
38 where regexp_substr (data_source, 'A-\S+|ABC\S+', 1, column_value) is not null
39 /
ID REF_NUM
---------- ------------------------------
1 A-123456789
1 ABC123456790
1 A-123456791
1 ABC123456792
1 ABC123456793
2 A-123456794
2 ABC123456795
2 ABC123456796
2 A-123456797
2 ABC123456798
10 rows selected.
SQL>
【讨论】:
嗨@Littlefoot,它可以工作,但如果解析 HugeClob,性能会很差。任何解决方法来最小化空记录而不是通过 Where ref_num is not null… 您是在解析一个巨大的 CLOB,还是在解析整个表(“n”行和 CLOB 列)?因为,如果是前者,恐怕你无能为力。如果是后者,那么是的 - 它可以被重写并 - 希望 - 运行得更快一些。 嗨@Littlefoot,我正在为每条记录解析一个 col hugeclob,每条记录大约 5,000 个字符...... 我又加了一个例子;请看一下。 嗨@Littlefoot,非常感谢!以上是关于使用 Oracle Query 显示所有匹配的记录的主要内容,如果未能解决你的问题,请参考以下文章