Oracle
 sql >> Database >  >> RDS >> Oracle

Trova tutte le corrispondenze in un varchar2()

Ottima domanda! Ecco un violino mostrando come interrogare le corrispondenze in un set di risultati.

Ed ecco la lunga spiegazione nel caso in cui la query in Fiddle non abbia senso :)

Sto usando una tabella denominata RegEx_Test con una colonna MyVal . Ecco il contenuto della tabella:

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]

La tua espressione regolare è questa:\[[[:alpha:]][[:digit:]]{1,2}\] . È lo stesso dell'altra risposta tranne che con POSIX :alpha: e :digit: indicatori, che sono più sicuri in caso di set di caratteri internazionali.

Innanzitutto, devi conoscere il numero massimo di corrispondenze su qualsiasi riga. Usa REGEXP_COUNT per questo:

SELECT MAX(REGEXP_COUNT(MyVal, '\[[[:alpha:]][[:digit:]]{1,2}\]'))
  FROM Regex_Test

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

Usa quel conteggio massimo per ottenere una tabella "contatore" (che è il SELECT ... FROM DUAL sotto) e unisciti alla tabella contatore con una query che estrarrà i tuoi valori utilizzando REGEXP_SUBSTR . REGEXP_SUBSTR ha un parametro "occorrenza" e questo utilizzerà il 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

Ecco un esempio eseguito sulla mia tabella (risultati parziali):

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

A questo punto hai un set di risultati di singole corrispondenze, più valori nulli in cui una riga ha un numero di corrispondenze inferiore al massimo. Le partite hanno ancora le parentesi circostanti. Circonda il tutto con una query esterna che filtrerà i valori null e rimuoverà le parentesi e avrai la tua lista finale:

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

Questa è la query che si trova su Fiddle e può essere utilizzata in un'altra query.