web-dev-qa-db-fra.com

Comment compter le nombre d'occurrences d'un caractère dans une valeur Oracle varchar?

Comment compter le nombre d'occurrences du caractère - dans une chaîne varchar2?

Exemple:

select XXX('123-345-566', '-') from dual;
----------------------------------------
2
30
Ula Krukar

Voici:

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

Techniquement, si la chaîne que vous voulez vérifier ne contient que le caractère que vous voulez compter, la requête ci-dessus retournera NULL; la requête suivante donnera la bonne réponse dans tous les cas:

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

Le dernier 0 dans coalesce attrape le cas où vous comptez dans une chaîne vide (c'est-à-dire NULL, car length (NULL) = NULL dans Oracle).

57
Flukey

REGEXP_COUNT devrait faire l'affaire:

select REGEXP_COUNT('123-345-566', '-') from dual;
52
Borodin

Voici une idée: essayez de remplacer tout ce qui n'est pas un caractère de tiret par une chaîne vide. Puis compte combien de tirets sont restés.

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

J'ai pensé à

 SELECT LENGTH('123-345-566') - LENGTH(REPLACE('123-345-566', '-', '')) FROM DUAL;
3
Hugh Jones

Je viens de faire face à un problème très similaire ... MAIS RegExp_Count n'a pas pu le résoudre . Combien de fois la chaîne '16, 124,3,3,1,0, 'contient', 3, '? Comme nous le voyons 2 fois, mais RegExp_Count ne retourne que 1. La même chose s’applique à '' bbaaaacc 'et lorsque vous y regardez' aa '- devrait être 3 fois et RegExp_Count ne renvoie que 2.

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

J'ai perdu un peu de temps pour rechercher une solution sur le Web. Impossible de trouver ... donc j'ai écrit ma propre fonction qui renvoie le nombre TRUE réel. J'espère que ce sera 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;
3
GrzegorzD

voici une solution qui fonctionnera aussi bien pour les caractères que pour les sous-chaînes:

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

où a est la chaîne dans laquelle vous recherchez l'occurrence de b

bonne journée!

1
stefan
SELECT {FN LENGTH('123-345-566')} - {FN LENGTH({FN REPLACE('123-345-566', '#', '')})} FROM DUAL
0
Abel Pinto
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  ='_';
0
Kunal