如何计算 Oracle varchar 值中字符的出现次数?

Posted

技术标签:

【中文标题】如何计算 Oracle varchar 值中字符的出现次数?【英文标题】:How to count the number of occurrences of a character in an Oracle varchar value? 【发布时间】:2011-12-31 10:51:50 【问题描述】:

如何计算 varchar2 字符串中字符 - 的出现次数?

例子:

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

【问题讨论】:

关于性能,我们有趣地发现REGEXP_COUNT 解决方案比LENGTH-LENGTH(REPLACE()) 方法慢约5 倍(更多CPU 时间消耗)。 Oracle 11.2.0.4 Linux x86 64 位 【参考方案1】:

给你:

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;

coalesce 中的最后一个 0 捕捉到您在空字符串中计数的情况(即 NULL,因为 ORACLE 中的 length(NULL) = NULL)。

【讨论】:

这个答案非常聪明;)【参考方案2】:

REGEXP_COUNT 应该可以解决问题:

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

【讨论】:

仅在 Oracle 11 中支持。不过很好的解决方案。 +1 很高兴知道还有一个 REGEXP_COUNT 函数。 耻辱。没注意到 OP 是 10g【参考方案3】:

这是一个想法:尝试用空字符串替换不是破折号字符的所有内容。然后计算剩余的破折号。

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

【讨论】:

【参考方案4】:

我刚刚遇到了非常相似的问题...但是 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;

我浪费了一些时间在网络上研究解决方案。找不到...所以我编写了自己的函数来返回 TRUE 的出现次数。希望对你有用。

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;

【讨论】:

正则表达式的工作原理是遍历字符串,而不是每次都从头开始搜索,因此REGEXP_COUNT() 将始终正确地(从正则表达式的 POV)返回 1 为您的例子以及类似的例子。它找到,3, 的第一次出现,然后从字符串中的下一个位置开始,再次查找该模式,但没有找到。【参考方案5】:

我想到了

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

【讨论】:

【参考方案6】:

你可以试试这个

select count( distinct pos) from
(select instr('123-456-789', '-', level) as pos from dual
  connect by level <=length('123-456-789'))
where nvl(pos, 0) !=0

它“正确”地计算 'bbaaaacc' 中有多少个 'aa'

select count( distinct pos) from
(select instr('bbaaaacc', 'aa', level) as pos from dual
  connect by level <=length('bbaaaacc'))
where nvl(pos, 0) !=0

【讨论】:

【参考方案7】:

这是一个适用于字符和子字符串的解决方案:

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

其中 a 是您在其中搜索 b 出现的字符串

祝你有美好的一天!

【讨论】:

【参考方案8】:
SELECT FN LENGTH('123-345-566') - FN LENGTH(FN REPLACE('123-345-566', '#', '')) FROM DUAL

【讨论】:

这是什么语法? 你也应该提供一些解释【参考方案9】:
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  ='_';

【讨论】:

虽然此代码可能会回答问题,但提供有关它如何和/或为什么解决问题的额外上下文将提高​​答案的长期价值。

以上是关于如何计算 Oracle varchar 值中字符的出现次数?的主要内容,如果未能解决你的问题,请参考以下文章

oracle中varchar2类型与integer类型的变量进行运算

oracle中如何取消列值中的空格

oracle中如何取消列值中的空格

如何从带有周围字符的 oracle varchar 获取日期时间

mysql与oracle 表字段定义比较

如何在 Oracle 表的 varchar 列中的第二个和第四个字符之后插入“/”