0

我们知道 stringutils 函数 CountMatches() - CountMatches - 计算一个字符串在另一个字符串中出现的次数。我需要 postgresql 中的等效查询来计算另一个字符串中出现的次数。

任何想法将不胜感激

4

3 回答 3

1

regexp_matches()

regexp_matches()@Igor 建议和@Tomasz 实施的解决方案简短而优雅,但有两个缺点:

  • 正则表达式功能强大,但通常比简单函数慢得多。
  • 聚合步骤使得集成到更大的查询变得不简单。

要在具有多个源行的查询中使用它:

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演示了所有内容。

于 2014-08-30T20:10:06.073 回答
1

您可以将 regexp_matches 与贪婪开关一起使用:

select count ( * )
from regexp_matches ( 'abc abc', 'ab', 'g' ); -- result is 2
于 2014-08-30T12:09:49.920 回答
0

PostgreSQL does not have that function, but you can work around it this way:

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

There may be edge cases that do not work correctly.

regexp_split_to_array creates an array with the non-matching parts. The number of elements in the array is one more than the number of matches (at least for normal cases). So, array_length and -1 produce the count of matches.

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;
于 2014-08-30T08:11:37.657 回答