2016-04-02 298 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')); 
相关问题