2011-11-17 35 views
25

¿Cómo puedo contar el número de apariciones del carácter - en una cadena varchar2?¿Cómo contar el número de apariciones de un carácter en un valor varchar de Oracle?

Ejemplo:

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

En cuanto al rendimiento que curiosamente encontró la solución 'REGEXP_COUNT' sea aproximadamente 5 veces más lenta (más tiempo de CPU que consume) que el' LONGITUD-LONGITUD (SUSTITUIR()) 'enfoque. Oracle 11.2.0.4 Linux x86 64-bit –

Respuesta

54

Aquí van:

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

Técnicamente, si la cadena que desea comprobar sólo contiene el carácter que desea contar, la consulta anterior devolverá NULL; la siguiente consulta dará la respuesta correcta en todos los casos:

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

Los últimos 0 en coalesce capturas el caso de que usted está contando en una cadena vacía (es decir, NULL, debido a la longitud (NULL) = NULL en Oracle) .

+0

Muy inteligente esta respuesta;) – kevthanewversi

10

He aquí una idea: intente reemplazar todo lo que no es un char tablero con cadena vacía. Luego cuenta cuántos guiones permanecieron.

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

REGEXP_COUNT debe hacer el truco:

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

Solo compatible con Oracle 11. Buena solución. – Flukey

+0

+1 es bueno saber que también hay una función REGEXP_COUNT. – bpgergo

+0

Vergüenza. No notó que el OP estaba en 10g – Borodin

2

pensé en

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

También debe proporcionar alguna explicación a su código. – brimborium

+0

¿Qué tipo de sintaxis es esta? – collapsar

+0

También debe proporcionar alguna explicación – Faisal

1

aquí es una solución que funcione para ambos caracteres y subcadenas:

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

donde a es la cuerda en la que tu mar rch la ocurrencia de b

tenga un buen día!

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

Si bien este código puede responder a la pregunta, proporcionar un contexto adicional sobre cómo y/o por qué resuelve el problema mejoraría el valor a largo plazo de la respuesta. – kayess

2

I justed enfrentó un problema muy similar ... PERO RegExp_Count no lo pudo resolver. ¿Cuántas veces la cadena '16, 124,3,3,1,0, 'contiene', 3, '? Como vemos 2 veces, pero solo RegExp_Count Devoluciones en 1. Lo mismo es con '' bbaaaacc' y cuando se mira en él 'aa' - debe ser 3 veces y Devoluciones en RegExp_Count acaba 2.

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

he perdido algo de tiempo para buscar soluciones en la web. No pude 'encontrar ... así que escribí mi propia función que devuelve el número VERDADERO de ocurrencia. Espero que sea útil.

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; 
Cuestiones relacionadas