GolezTrolの回答を拡張すると、正規表現を使用して、実行する再帰クエリの数を大幅に減らすことができます。
select instr('SSSRNNSRSSR','R', 1, level)
from dual
connect by level <= regexp_count('SSSRNNSRSSR', 'R')
REGEXP_COUNT()は、パターンが一致した回数(この場合は R
)を返します。 SSSRNNSRSSR
に存在します 。これにより、再帰のレベルが必要な正確な数に制限されます。
INSTR()は、文字列内のRのインデックスを検索するだけです。 レベルコード> は再帰の深さですが、この場合はレベル th でもあります 必要な繰り返しの数に制限したため、文字列の出現。
選択したい文字列がより複雑な場合は、INSTR()ではなく正規表現とREGEXP_INSTR()を使用できますが、速度が遅くなり(それほどではありません)、必要な場合を除いて不要です。
要求に応じた単純なベンチマーク:
2つのCONNECTBYソリューションは、このサイズの文字列でREGEXP_COUNTを使用すると20%高速になることを示しています。
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
パイプライン化されたテーブル関数はかなり遅くなりますが、一致するものが多い大きな文字列に対してどのように機能するかを確認するのは興味深いことです。
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