Mở rộng câu trả lời của GolezTrol, bạn có thể sử dụng biểu thức chính quy để giảm đáng kể số lượng truy vấn đệ quy mà bạn thực hiện:
select instr('SSSRNNSRSSR','R', 1, level)
from dual
connect by level <= regexp_count('SSSRNNSRSSR', 'R')
REGEXP_COUNT () trả về số lần mẫu đối sánh, trong trường hợp này là số lần R
tồn tại trong SSSRNNSRSSR
. Điều này giới hạn mức đệ quy đến con số chính xác mà bạn cần.
INSTR () chỉ đơn giản là tìm kiếm chỉ mục của R trong chuỗi của bạn. level
là độ sâu của đệ quy nhưng trong trường hợp này nó cũng là mức th sự xuất hiện của chuỗi vì chúng tôi đã giới hạn số lần đệ quy bắt buộc.
Nếu chuỗi bạn muốn chọn phức tạp hơn, bạn có thể sử dụng biểu thức chính quy ans REGEXP_INSTR () thay vì INSTR () nhưng nó sẽ chậm hơn (không nhiều) và không cần thiết trừ khi được yêu cầu.
Điểm chuẩn đơn giản theo yêu cầu:
Hai giải pháp CONNECT BY sẽ chỉ ra rằng việc sử dụng REGEXP_COUNT nhanh hơn 20% trên một chuỗi có kích thước này.
SQL> set timing on
SQL>
SQL> -- CONNECT BY with REGEX
SQL> declare
2 type t__num is table of number index by binary_integer;
3 t_num t__num;
4 begin
5 for i in 1 .. 100000 loop
6 select instr('SSSRNNSRSSR','R', 1, level)
7 bulk collect into t_num
8 from dual
9 connect by level <= regexp_count('SSSRNNSRSSR', 'R')
10 ;
11 end loop;
12 end;
13 /
PL/SQL procedure successfully completed.
Elapsed: 00:00:03.94
SQL>
SQL> -- CONNECT BY with filter
SQL> declare
2 type t__num is table of number index by binary_integer;
3 t_num t__num;
4 begin
5 for i in 1 .. 100000 loop
6 select pos
7 bulk collect into t_num
8 from ( select substr('SSSRNNSRSSR', level, 1) as character
9 , level as pos
10 from dual t
11 connect by level <= length('SSSRNNSRSSR') )
12 where character = 'R'
13 ;
14 end loop;
15 end;
16 /
PL/SQL procedure successfully completed.
Elapsed: 00:00:04.80
Hàm pipelined table chậm hơn một chút, mặc dù sẽ rất thú vị khi xem nó hoạt động như thế nào trên các chuỗi lớn với nhiều khớp.
SQL> -- PIPELINED TABLE FUNCTION
SQL> declare
2 type t__num is table of number index by binary_integer;
3 t_num t__num;
4 begin
5 for i in 1 .. 100000 loop
6 select *
7 bulk collect into t_num
8 from table(string_indexes('SSSRNNSRSSR','R'))
9 ;
10 end loop;
11 end;
12 /
PL/SQL procedure successfully completed.
Elapsed: 00:00:06.54