2016-04-02 241 views
18

如何計算PostgreSQL中字符串中子字符串的出現次數?計算PostgreSQL中字符串中子字符串的出現次數


例子:

我有一個表

CREATE TABLE test."user" 
(
    uid integer NOT NULL, 
    name text, 
    result integer, 
    CONSTRAINT pkey PRIMARY KEY (uid) 
) 

我想寫一個查詢,以便result包含列如何子oname包含的許多事件。例如,如果在一行中,namehello world,則列result應該包含2,因爲字符串hello world中有兩個o

換句話說,我想編寫一個查詢,將作爲輸入:

enter image description here

和更新result柱:

enter image description here


我我知道功能regexp_matches及其g選項,它指示需要掃描完整(g =全局)字符串以查看是否存在所有出現的子字符串)。

實施例:

SELECT * FROM regexp_matches('hello world', 'o', 'g'); 

返回

{o} 
{o} 

SELECT COUNT(*) FROM regexp_matches('hello world', 'o', 'g'); 

返回

2 

但是我不知道如何編寫UPDATE查詢來更新result列,以便包含列name包含的子字符串的出現次數。

+0

的[PostgreSQL的文本中出現的時間串的計數數]可能的複製(http://stackoverflow.com/questions/25757194/postgresql -count-number-of-times-substring-occurrence-in-text) –

回答

21

一個常見的解決方案是基於這樣的邏輯:更換用空字符串搜索字符串和由搜索字符串的長度

(CHAR_LENGTH(name) - CHAR_LENGTH(REPLACE(name, 'substring', ''))) 
/CHAR_LENGTH('substring') 

因此劃分新舊長度之間的差:

UPDATE test."user" 
SET result = 
    (CHAR_LENGTH(name) - CHAR_LENGTH(REPLACE(name, 'o', ''))) 
    /CHAR_LENGTH('o'); 
這樣做的
+0

這是一個可靠的答案,它是正確的。你可能對我寫的[所有這樣做的方法]感興趣(http://dba.stackexchange.com/a/166763/2639) –

+0

謝謝!有誰知道,爲什麼沒有簡單的方法?我的意思是,REPLACE已經經歷了掃描所有事件的整個字符串的麻煩,爲什麼沒有事情做REPLACE的一半工作 - 只需計算事件 –

+0

@AleksandrLevchuk:那麼,你可以編寫自己的用戶定義函數做這個計算,例如在https://www.enterprisedb.com/docs/en/9.5/eeguide/EDB_Postgres_Enterprise_Guide.1.041.html中有Oracle的「REGEXP_COUNT」。 – dnoeth

13

甲Postgres'y方式字符串轉換爲陣列和計數陣列的長度(和然後減去1):

select array_length(string_to_array(name, 'o'), 1) - 1 

請注意,這也適用於較長的子字符串。

因此:

update test."user" 
    set result = array_length(string_to_array(name, 'o'), 1) - 1; 
+2

如果有人需要regexp,這個解決方案使用「regexp_split_to_array」而不是「string_to_array」。 –

+0

這個解決方案比@ dnoeth的建議慢得多。我不認爲它更多 - Postgres-y。當事情更快,更方便時,我認爲我們稱之爲*更好*。 =) –

+1

@EvanCarroll不幸的是,dnoeth的回答不適用於正則表達式匹配,因爲您可能不知道匹配的長度。這個答案適用於正則表達式匹配和原始字符串匹配。我認爲我們稱之爲_better_的解決方案適用於你試圖做的所有事情:) – WebWanderer

0

其他方式:

UPDATE test."user" SET result = length(regexp_replace(name, '[^o]', '', 'g')); 
相關問題