2011-11-17 21 views
25

Come posso contare il numero di occorrenze del carattere - in una stringa varchar2?Come contare il numero di occorrenze di un carattere in un valore varchar Oracle?

Esempio:

select XXX('123-345-566', '-') from dual; 
---------------------------------------- 
2 
+0

Per quanto riguarda le prestazioni che è interessante notare trovato la soluzione 'REGEXP_COUNT' ad essere circa 5 volte più lento (più tempo di CPU che consumano) rispetto al' LUNGHEZZA-LUNGHEZZA (replace()) 'approccio. Oracle 11.2.0.4 Linux x86 64-bit –

risposta

54

Qui si va:

select length('123-345-566') - length(replace('123-345-566','-',null)) 
from dual; 

Tecnicamente, se la stringa si desidera controllare contiene solo il carattere che si desidera contare, la query precedente restituirà NULL; la seguente query darà la risposta corretta in tutti i casi:

select coalesce(length('123-345-566') - length(replace('123-345-566','-',null)), length('123-345-566'), 0) 
from dual; 

Gli ultimi 0 a coalesce catture caso in cui si sta contando in una stringa vuota (cioè NULL, poiché la lunghezza (NULL) = NULL in Oracle) .

+0

Molto intelligente questa risposta;) – kevthanewversi

10

Ecco un'idea: provare a sostituire tutto ciò che non è un char trattino con stringa vuota. Quindi conta quanti trattini sono rimasti.

select length(regexp_replace('123-345-566', '[^-]', '')) from dual 
49

REGEXP_COUNT dovrebbe fare il trucco:

select REGEXP_COUNT('123-345-566', '-') from dual; 
+3

Solo supportato in Oracle 11. Bella soluzione però. – Flukey

+0

+1 è bene sapere che esiste anche una funzione REGEXP_COUNT. – bpgergo

+0

Vergogna. Non ho notato che l'OP era in 10g – Borodin

2

ho pensato di

SELECT LENGTH('123-345-566') - LENGTH(REPLACE('123-345-566', '-', '')) FROM DUAL; 
0
SELECT {FN LENGTH('123-345-566')} - {FN LENGTH({FN REPLACE('123-345-566', '#', '')})} FROM DUAL 
+0

Dovresti anche fornire qualche spiegazione al tuo codice. – brimborium

+0

Che tipo di sintassi è questa? – collapsar

+0

È inoltre necessario fornire alcune spiegazioni – Faisal

1

ecco una soluzione che funzionerà per entrambi i personaggi e sottostringhe:

select (length('a') - nvl(length(replace('a','b')),0))/length('b') 
    from dual 

dove a è la stringa in cui tu mare la presenza di b

buona giornata!

0
select count(*) 
from (
     select substr('K_u_n_a_l',level,1) str 
     from dual 
     connect by level <=length('K_u_n_a_l') 
    ) 
where str ='_'; 
+1

Sebbene questo codice possa rispondere alla domanda, fornire un contesto aggiuntivo su come e/o perché risolve il problema migliorerebbe il valore a lungo termine della risposta. – kayess

2

ho justed fronte problema molto simile ... MA RegExp_Count non poteva risolvere esso. Quante volte string '16, 124,3,3,1,0, 'contiene', 3, '? Come si vede 2 volte, ma RegExp_Count Restituzioni solo 1. La stessa cosa è con '' bbaaaacc' e quando si cerca in essa 'AA' - dovrebbe essere 3 volte e restituisce RegExp_Count solo 2.

select REGEXP_COUNT('336,14,3,3,11,0,' , ',3,') from dual; 
select REGEXP_COUNT('bbaaaacc' , 'aa') from dual; 

ho perso un po' di tempo per cercare soluzioni sul web. Impossibile trovare ... così ho scritto la mia funzione che restituisce il vero numero di occurance. Spero che sarà utile.

CREATE OR REPLACE FUNCTION EXPRESSION_COUNT(pEXPRESSION VARCHAR2, pPHRASE VARCHAR2) RETURN NUMBER AS 
    vRET NUMBER := 0; 
    vPHRASE_LENGTH NUMBER := 0; 
    vCOUNTER NUMBER := 0; 
    vEXPRESSION VARCHAR2(4000); 
    vTEMP VARCHAR2(4000); 
BEGIN 
    vEXPRESSION := pEXPRESSION; 
    vPHRASE_LENGTH := LENGTH(pPHRASE); 
    LOOP 
    vCOUNTER := vCOUNTER + 1; 
    vTEMP := SUBSTR(vEXPRESSION, 1, vPHRASE_LENGTH); 
    IF (vTEMP = pPHRASE) THEN   
     vRET := vRET + 1; 
    END IF; 
    vEXPRESSION := SUBSTR(vEXPRESSION, 2, LENGTH(vEXPRESSION) - 1); 
    EXIT WHEN (LENGTH(vEXPRESSION) = 0) OR (vEXPRESSION IS NULL); 
    END LOOP; 
    RETURN vRET; 
END; 
Problemi correlati