我们知道字符串函数CountMatches()-CountMatches-统计一个字符串在另一个字符串中的出现次数。我在postgresql中需要一个等价的查询来计算一个字符串在另一个字符串中的出现次数。
任何想法都会感谢
您可以将regexp_matches与贪婪开关一起使用:
select count ( * )
from regexp_matches ( 'abc abc', 'ab', 'g' ); -- result is 2
regexp_matches()
@Igor建议和@Tomasz实现的regexp_matches()
解决方案简短而优雅,但有两个缺点:
- 正则表达式功能强大,但通常比简单函数慢得多
- 聚合步骤使集成到更大的查询中变得非常简单
要在具有多个源行的查询中使用它:
SELECT t.*, count(match) AS ct
FROM tbl t
LEFT JOIN LATERAL regexp_matches(t.string, 'ab', 'g') match ON TRUE
GROUP BY t.tbl_id
ORDER BY t.tbl_id;
或者:
SELECT t.*, m.ct
FROM tbl t
LEFT JOIN LATERAL (
SELECT count(*) AS ct
FROM regexp_matches(t.string, 'ab', 'g')
) m ON TRUE
ORDER BY t.tbl_id;
replace()
/length()
这个表达没有那么优雅,但应该更快,可以更容易地在片场使用:
SELECT (length(col) - length(replace(col, 'match', ''))) / length('match') AS ct;
您可以将其封装在一个简单的SQL函数中:
CREATE OR REPLACE FUNCTION f_count_matches(_string text, _match text)
RETURNS int LANGUAGE sql IMMUTABLE STRICT AS
$$
SELECT (length(_string) - length(replace(_string, _match, ''))) / length(_match)
$$;
然后:
SELECT f_count_matches('abc cab,xabx abab', 'ab');
SQL Fiddle演示所有内容。
PostgreSQL没有这个功能,但您可以通过以下方式解决它:
SELECT array_length(regexp_split_to_array('axbxcxdxexfxg','b'),1)-1; -- returns 1
SELECT array_length(regexp_split_to_array('axbxcxdxexfxg','x'),1)-1; -- returns 6
SELECT array_length(regexp_split_to_array('axbxcxdxexfxg','z'),1)-1; -- returns 0
可能存在无法正常工作的边缘情况。
regexp_split_to_array
创建一个具有不匹配部分的数组。数组中的元素数比匹配数多一个(至少在正常情况下是这样)。因此,array_length
和-1
产生匹配的计数。
CREATE FUNCTION num_matches(string text,pattern text)
RETURNS int AS $$
SELECT array_length(regexp_split_to_array(string,pattern),1)-1;
$$ LANGUAGE SQL STABLE;