Как посчитать количество вхождений символа в значение Oracle varchar? - PullRequest
30 голосов
/ 17 ноября 2011

Как подсчитать количество вхождений символа - в строку varchar2?

Пример:

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

Ответы [ 8 ]

59 голосов
/ 17 ноября 2011

Вот, пожалуйста:

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

Технически, если строка, которую вы хотите проверить, содержит только символ, который вы хотите считать, вышеприведенный запрос вернет NULL;следующий запрос даст правильный ответ во всех случаях:

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

Финальный 0 в coalesce перехватывает случай, когда вы рассчитываете пустую строку (то есть NULL, потому что length (NULL) =NULL в ORACLE).

57 голосов
/ 17 ноября 2011

REGEXP_COUNT должны сделать трюк:

select REGEXP_COUNT('123-345-566', '-') from dual;
11 голосов
/ 17 ноября 2011

Вот идея: попробуйте заменить все, что не является тире-символом, пустой строкой.Затем посчитайте, сколько осталось штрихов.

select length(regexp_replace('123-345-566', '[^-]', '')) from dual
4 голосов
/ 12 января 2018

Я только что столкнулся с очень похожей проблемой ... НО RegExp_Count не смог ее решить.Сколько раз строка '16, 124,3,3,1,0, 'содержит', 3, '?Как мы видим 2 раза, но RegExp_Count возвращает только 1. То же самое происходит с '' bbaaaacc ', а при просмотре' aa '- должно быть 3 раза, а RegExp_Count возвращает только 2.

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

Я потерялнекоторое время, чтобы исследовать решение в сети.Не могу найти ... поэтому я написал свою собственную функцию, которая возвращает ИСТИННОЕ число вхождения.Надеюсь, это будет полезно.

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 голосов
/ 17 ноября 2011

Я думал о

 SELECT LENGTH('123-345-566') - LENGTH(REPLACE('123-345-566', '-', '')) FROM DUAL;
1 голос
/ 26 февраля 2014

вот решение, которое будет работать как для символов, так и для подстрок:

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

, где a - строка, в которой вы ищете вхождение b

хорошего дня!

0 голосов
/ 27 апреля 2016
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 голосов
/ 31 октября 2012
SELECT {FN LENGTH('123-345-566')} - {FN LENGTH({FN REPLACE('123-345-566', '#', '')})} FROM DUAL
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...