2011-11-17 78 views
25

Làm cách nào để đếm số lần xuất hiện của ký tự - trong chuỗi varchar2?Làm thế nào để đếm số lần xuất hiện của một ký tự trong một giá trị varchar của Oracle?

Ví dụ:

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

Về hiệu suất, chúng tôi đã tìm thấy giải pháp 'REGEXP_COUNT' chậm hơn khoảng 5 lần (tốn nhiều thời gian hơn CPU) so với phương pháp' LENGTH-LENGTH (REPLACE()) '. Oracle 11.2.0.4 Linux x86 64-bit –

Trả lời

54

Ở đây bạn đi:

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

Về mặt kỹ thuật, nếu chuỗi bạn muốn kiểm tra chỉ chứa các ký tự mà bạn muốn đếm, các truy vấn trên sẽ trả về NULL; các truy vấn sau đây sẽ cung cấp cho các câu trả lời đúng trong mọi trường hợp:

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

Các thức 0 trong coalesce bắt trường hợp bạn đang đếm trong một chuỗi rỗng (tức là NULL, vì chiều dài (NULL) = NULL trong ORACLE) .

+0

Rất thông minh câu trả lời này;) – kevthanewversi

10

Dưới đây là một ý tưởng: cố gắng thay thế tất cả những gì không phải là một char dấu gạch ngang với chuỗi rỗng. Sau đó đếm còn bao nhiêu dấu gạch ngang.

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

REGEXP_COUNT nên làm các trick:

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

Chỉ được hỗ trợ trong Oracle 11. Mặc dù giải pháp tốt. – Flukey

+0

+1 bạn cũng nên biết rằng có một hàm REGEXP_COUNT. – bpgergo

+0

Xấu hổ. Không nhận thấy OP là trên 10g – Borodin

2

tôi nghĩ

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

Bạn cũng nên cung cấp một số giải thích cho mã của bạn. – brimborium

+0

Loại cú pháp này là gì? – collapsar

+0

Bạn cũng nên cung cấp một số giải thích – Faisal

1

đây là một giải pháp mà sẽ hoạt động cho cả nhân vật và chuỗi con:

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

nơi a là chuỗi mà bạn biển rch sự xuất hiện của b

có một ngày tốt đẹp!

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

Mặc dù mã này có thể trả lời câu hỏi, cung cấp thêm ngữ cảnh về cách thức và/hoặc lý do giải quyết vấn đề sẽ cải thiện giá trị lâu dài của câu trả lời. – kayess

2

Tôi vừa gặp phải vấn đề rất giống nhau ... NHƯNG RegExp_Count không thể giải quyết được. Chuỗi bao nhiêu lần '16, 124,3,3,1,0, 'chứa', 3, '? Như chúng ta thấy 2 lần, nhưng RegExp_Count trả về chỉ 1. Cùng một điều là với '' bbaaaacc' và khi nhìn vào nó 'aa' - nên 3 lần và RegExp_Count trả về chỉ 2.

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

tôi bị mất một số thời gian để nghiên cứu giải pháp trên web. Không thể 'tìm thấy ... vì vậy tôi đã viết hàm của riêng tôi trả về số lượng TRUE của sự xuất hiện. Hy vọng nó sẽ hữu ích.

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; 
Các vấn đề liên quan