CountMatches()等效Postgres查询

时间:2014-08-30 05:25:23

标签: java postgresql string-utils

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

任何想法都会赞赏

3 个答案:

答案 0 :(得分:1)

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

select count ( * )
from regexp_matches ( 'abc abc', 'ab', 'g' ); -- result is 2

答案 1 :(得分:1)

regexp_matches()

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

  • 正则表达式功能强大,但通常比简单函数慢得多。
  • 汇总步骤使得集成到更大的查询中变得非常重要。

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

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展示所有。

答案 2 :(得分:0)

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;