Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Encontre todas as correspondências em um varchar2()


Ótima pergunta! Aqui está um violino mostrando como consultar as correspondências em um conjunto de resultados.

E aqui está a longa explicação caso a consulta no Fiddle não faça sentido :)

Estou usando uma tabela chamada RegEx_Test com uma coluna MyVal . Segue o conteúdo da tabela:
MyVal
------------------------------
[A1][abc][B23][D123]a33[bx5]
[Z15][ax0][B0][F13]R3
[X215][A3A][J99]F33F33G24[43][R3]
[Z99][c1][F3][d33]3x24[Y3][f13]
[9a][D41][Q39][XX12]B27[T03][J12]

Sua expressão regular é esta:\[[[:alpha:]][[:digit:]]{1,2}\] . É o mesmo que na outra resposta, exceto com o POSIX :alpha: e :digit: indicadores, que são mais seguros no caso de conjuntos de caracteres internacionais.

Primeiro, você precisa saber o número máximo de correspondências em qualquer linha. Usar REGEXP_COUNT por esta:
SELECT MAX(REGEXP_COUNT(MyVal, '\[[[:alpha:]][[:digit:]]{1,2}\]'))
  FROM Regex_Test

MAX(REGEXP_COUNT(My...
----------------------
                     6

Use essa contagem máxima para obter uma tabela de "contadores" (que é o SELECT ... FROM DUAL abaixo) e faça a junção cruzada da tabela do contador com uma consulta que extrairá seus valores usando REGEXP_SUBSTR . REGEXP_SUBSTR tem um parâmetro "occurrence" e que usará o Counter :
SELECT
  MyVal,
  Counter,
  REGEXP_SUBSTR(MyVal, '\[[[:alpha:]][[:digit:]]{1,2}\]', 1, Counter) Matched
FROM Regex_Test
CROSS JOIN (
   SELECT LEVEL Counter
   FROM DUAL
   CONNECT BY LEVEL <= (
     SELECT MAX(REGEXP_COUNT(MyVal, '\[[[:alpha:]][[:digit:]]{1,2}\]'))
     FROM Regex_Test)) Counters

Aqui está um exemplo executado na minha tabela (resultados parciais):
MyVal                              Counter Matched
---------------------------------- ------- -------
[9a][D41][Q39][XX12]B27[T03][J12]        1 [D41]
[9a][D41][Q39][XX12]B27[T03][J12]        2 [Q39]
[9a][D41][Q39][XX12]B27[T03][J12]        3 [T03]
[9a][D41][Q39][XX12]B27[T03][J12]        4 [J12]
[9a][D41][Q39][XX12]B27[T03][J12]        5
[9a][D41][Q39][XX12]B27[T03][J12]        6
[A1][abc][B23][D123]a33[bx5]             1 [A1]
[A1][abc][B23][D123]a33[bx5]             2 [B23]
[A1][abc][B23][D123]a33[bx5]             3
... and so on - total is 30 rows

Neste ponto, você tem um conjunto de resultados de correspondências individuais, além de nulos em que uma linha teve menos do que o máximo de correspondências. As partidas ainda têm seus suportes ao redor. Cerque tudo com uma consulta externa que filtrará os nulos e removerá os colchetes, e você terá sua lista final:
SELECT SUBSTR(Matched, 2, LENGTH(Matched)-2) FROM (
  SELECT
    MyVal,
    Counter,
    REGEXP_SUBSTR(MyVal, '\[[[:alpha:]][[:digit:]]{1,2}\]', 1, Counter) Matched
  FROM Regex_Test
  CROSS JOIN (
     SELECT LEVEL Counter
     FROM DUAL
     CONNECT BY LEVEL <= (
       SELECT MAX(REGEXP_COUNT(MyVal, '\[[[:alpha:]][[:digit:]]{1,2}\]'))
       FROM Regex_Test)) Counters
) WHERE Matched IS NOT NULL

Esta é a consulta que está no Fiddle e pode ser usada em outra consulta.