简体   繁体   English

计算 PostgreSQL 中字符串中子字符串的出现次数

[英]Counting the number of occurrences of a substring within a string in PostgreSQL

How can I count the number of occurrences of a substring within a string in PostgreSQL?如何计算 PostgreSQL 中字符串中子字符串的出现次数?


Example:例子:

I have a table我有一张桌子

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

I want to write a query so that the result contains column how many occurrences of the substring o the column name contains.我想写一个查询,以便result包含列怎样子的许多事件oname包含的内容。 For instance, if in one row, name is hello world , the column result should contain 2 , since there are two o in the string hello world .例如,如果在一行中, namehello world ,则列result应包含2 ,因为字符串hello world有两个o

In other words, I'm trying to write a query that would take as input:换句话说,我正在尝试编写一个作为输入的查询:

在此处输入图片说明

and update the result column:并更新result列:

在此处输入图片说明


I am aware of the function regexp_matches and its g option, which indicates that the full ( g = global) string needs to be scanned for the presence of all occurrences of the substring).我知道函数regexp_matches及其g选项,这表明需要扫描完整的( g = global)字符串以查找所有出现的子字符串)。

Example:例子:

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

returns回报

{o}
{o}

and

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

returns回报

2

But I don't see how to write an UPDATE query that would update the result column in such a way that it would contain how many occurrences of the substring o the column name contains.但是我不知道如何编写一个UPDATE查询来更新result列,以便它包含列name包含的子字符串的出现次数。

A common solution is based on this logic: replace the search string with an empty string and divide the difference between old and new length by the length of the search string 一个常见的解决方案是基于这样的逻辑: 用空字符串替换搜索字符串,并将新旧长度之间的差异除以搜索字符串的长度

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

Hence: 因此:

UPDATE test."user"
SET result = 
    (CHAR_LENGTH(name) - CHAR_LENGTH(REPLACE(name, 'o', ''))) 
    / CHAR_LENGTH('o');

A Postgres'y way of doing this converts the string to an array and counts the length of the array (and then subtracts 1): Postgres的做法是将字符串转换为数组并计算数组的长度(然后减去1):

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

Note that this works with longer substrings as well. 请注意,这也适用于较长的子串。

Hence: 因此:

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

Return count of character, 返回字符数,

 SELECT (LENGTH('1.1.1.1') - LENGTH(REPLACE('1.1.1.1','.',''))) AS count
--RETURN COUNT OF CHARACTER '.'

另一种方式:

UPDATE test."user" SET result = length(regexp_replace(name, '[^o]', '', 'g'));
Occcurence_Count = LENGTH(REPLACE(string_to_search,string_to_find,'~'))-LENGTH(REPLACE(string_to_search,string_to_find,''))

This solution is a bit cleaner than many that I have seen, especially with no divisor. 这个解决方案比我见过的许多解决方案更清晰,特别是没有除数。 You can turn this into a function or use within a Select. 您可以将其转换为函数或在Select中使用。
No variables required. 无需变量。 I use tilde as a replacement character, but any character that is not in the dataset will work. 我使用tilde作为替换字符,但任何不在数据集中的字符都可以使用。

SELECT array_length(string_to_array('a long name here', 'o'),1)
  • 1 is for 1-dimension array 1 是一维数组
  • 'o' is the occurrence you want to count 'o' 是您要计算的出现次数

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM