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

Come rimuovere un valore specifico da una stringa separata da virgole in Oracle

Ecco una soluzione che utilizza solo funzioni di stringa standard (piuttosto che espressioni regolari), il che dovrebbe comportare un'esecuzione più rapida nella maggior parte dei casi; rimuove 3 solo quando è il primo carattere seguito da virgola, l'ultimo carattere preceduto da virgola, oppure preceduto e seguito da virgola, rimuove la virgola che lo precede al centro e rimuove la virgola che lo segue nel primo e terzo caso.

È in grado di rimuovere due 3 di fila (cosa che alcune delle altre soluzioni offerte non sono in grado di fare) lasciando al loro posto virgole consecutive (che presumibilmente stanno per NULL) e non disturbano numeri come 38 o 123.

La strategia consiste nel raddoppiare prima ogni virgola (sostituire , con ,, ) e aggiungere e anteporre una virgola (all'inizio e alla fine della stringa). Quindi rimuovi ogni occorrenza di ,3, . Da ciò che è rimasto, sostituisci ogni ,, indietro con un singolo , e infine rimuovere il , iniziale e finale .

with
     test_data ( str ) as (
       select '1,2,3,4,5'     from dual union all
       select '1,2,3,3,4,4,5' from dual union all
       select '12,34,5'       from dual union all
       select '1,,,3,3,3,4'   from dual
     )
select str,
       trim(both ',' from 
             replace( replace(',' || replace(str, ',', ',,') || ',', ',3,'), ',,', ',')
           ) as new_str
from   test_data
;

STR           NEW_STR
------------- ----------
1,2,3,4,5     1,2,4,5
1,2,3,3,4,4,5 1,2,4,4,5
12,34,5       12,34,5
1,,,3,3,3,4   1,,,4

4 rows selected.

Nota Come sottolineato da MT0 (vedi Commenti sotto), questo taglierà troppo se la stringa originale inizia o finisce con virgole. Per coprire quel caso, invece di avvolgere tutto all'interno di trim(both ',' from ...) Dovrei racchiudere il resto in una sottoquery e usare qualcosa come substr(new_str, 2, length(new_str) - 2) nella query esterna.