PostgreSQL:获取数组中指定元素的出现次数。

时间:2021-02-13 22:54:45

I need to calculate the count of occurrences of specified element in array, something like:

我需要计算数组中指定元素出现的次数,如:

elem_occurrences_count(ARRAY[a,b,c,a,a], a) = 3

elem_occurrences_count(ARRAY[a,b,c,a,a],a)= 3

elem_occurrences_count(ARRAY[a,b,c], d) = 0

elem_occurrences_count(数组(a,b,c),d)= 0

Is there any function in PostgreSQL that can be used to solve the problem? Any help is appreciated.

PostgreSQL中有什么函数可以用来解决这个问题吗?任何帮助都是感激。

4 个解决方案

#1


3  

You will need to unnest the array and then count the occurrences.

您将需要取消数组的嵌套,然后计算出现的次数。

with elements (element) as (
   select unnest(ARRAY['a','b','c','a','a'])
)
select count(*)
from elements
where element = 'a';

This can easily be embedded into a function:

这可以很容易地嵌入到一个函数中:

create or replace function count_elements(elements text[], to_find text)
  returns bigint
as
$body$
  select count(*) 
  from unnest(elements) element 
  where element =  to_find;
$body$
language sql;

Update

更新

Since Postgres 9.5 this can also be done using array_positions() which returns an array of positions where an element was found. The length of that array is the number of occurrences:

由于postgres9.5也可以使用array_positions(),它返回找到元素的位置数组。该数组的长度是出现的次数:

select cardinality(array_positions(ARRAY['a','b','c','a','a'], 'a'));

#2


1  

9.5+

There is an easier method now

现在有一种更简单的方法

SELECT
  sArray,
  c,
  coalesce(array_length( array_positions(sArray, c), 1 ),0) AS count
FROM ( VALUES
  (ARRAY['a','b','c','a','a'], 'a'),
  (ARRAY['a','b','c'], 'd')
) AS t(sArray,c);

   sarray    | c | count 
-------------+---+-------
 {a,b,c,a,a} | a |     3
 {a,b,c}     | d |     0
(2 rows)

#3


0  

More generic function is here;

这里有更一般的函数;

CREATE FUNCTION count_array_elements (
  i_elements pg_catalog.anyarray,
  i_element_to_find pg_catalog.anyelement,
  out count bigint
)
RETURNS bigint AS
$body$
BEGIN
  SELECT count(*) INTO count
  FROM unnest(i_elements) u
  WHERE u = i_element_to_find;
END;
$body$
LANGUAGE 'plpgsql'
IMMUTABLE
RETURNS NULL ON NULL INPUT;

With this way, we can query like this one below;

通过这种方式,我们可以像下面这样查询;

SELECT * FROM count_array_elements(array [ TRUE, TRUE, FALSE, FALSE, FALSE ], TRUE);

#4


0  

Thanks to all contributors here, I learnt a few things. I am building on work of others in this thread and others in *.

感谢这里所有的贡献者,我学到了一些东西。我正在构建这个线程中的其他人和*中的其他人的工作。

I tried to create a function that will count for all the unique elements in the array.

我尝试创建一个函数来计算数组中所有唯一的元素。

I was targeting returning a json but it seems you can only return as SETOF.

我的目标是返回json,但似乎只能返回SETOF。

result of count_element_3

由于count_element_3

CREATE OR REPLACE FUNCTION count_element_3(str_array text[])
RETURNS setof text
AS
$$
DECLARE
    unique_element_array text[];
    cardinality_array int[];
    retArray text[];
BEGIN
-- Find unique items first
    unique_element_array := array(select distinct unnest(str_array));
    FOR I IN array_lower(unique_element_array, 1)..array_upper(unique_element_array, 1) 
    LOOP
    cardinality_array[I] := (select cardinality(array_positions(str_array, unique_element_array[I])));
    retArray[I] := concat(unique_element_array[I],':',cardinality_array[I]);
    END LOOP;

RETURN QUERY SELECT(retArray::text);
END;
$$
LANGUAGE plpgsql 
VOLATILE 
RETURNS NULL ON NULL INPUT;

with t1 as (SELECT
  sArray,
  c,
  coalesce(array_length( array_positions(sArray, c), 1 ),0) AS count
FROM ( VALUES
  (ARRAY['a','b','c','a','a'], 'a'),
  (ARRAY['a','b','c'], 'd')
) AS t(sArray,c)
)

select sarray, count_element_3(sarray) from t1

    sarray          count_element_3 
    text[]          text
-------------------------------------
    "{a,b,c,a,a}"   "{c:1,a:3,b:1}"
    "{a,b,c}"       "{c:1,a:1,b:1}"

#1


3  

You will need to unnest the array and then count the occurrences.

您将需要取消数组的嵌套,然后计算出现的次数。

with elements (element) as (
   select unnest(ARRAY['a','b','c','a','a'])
)
select count(*)
from elements
where element = 'a';

This can easily be embedded into a function:

这可以很容易地嵌入到一个函数中:

create or replace function count_elements(elements text[], to_find text)
  returns bigint
as
$body$
  select count(*) 
  from unnest(elements) element 
  where element =  to_find;
$body$
language sql;

Update

更新

Since Postgres 9.5 this can also be done using array_positions() which returns an array of positions where an element was found. The length of that array is the number of occurrences:

由于postgres9.5也可以使用array_positions(),它返回找到元素的位置数组。该数组的长度是出现的次数:

select cardinality(array_positions(ARRAY['a','b','c','a','a'], 'a'));

#2


1  

9.5+

There is an easier method now

现在有一种更简单的方法

SELECT
  sArray,
  c,
  coalesce(array_length( array_positions(sArray, c), 1 ),0) AS count
FROM ( VALUES
  (ARRAY['a','b','c','a','a'], 'a'),
  (ARRAY['a','b','c'], 'd')
) AS t(sArray,c);

   sarray    | c | count 
-------------+---+-------
 {a,b,c,a,a} | a |     3
 {a,b,c}     | d |     0
(2 rows)

#3


0  

More generic function is here;

这里有更一般的函数;

CREATE FUNCTION count_array_elements (
  i_elements pg_catalog.anyarray,
  i_element_to_find pg_catalog.anyelement,
  out count bigint
)
RETURNS bigint AS
$body$
BEGIN
  SELECT count(*) INTO count
  FROM unnest(i_elements) u
  WHERE u = i_element_to_find;
END;
$body$
LANGUAGE 'plpgsql'
IMMUTABLE
RETURNS NULL ON NULL INPUT;

With this way, we can query like this one below;

通过这种方式,我们可以像下面这样查询;

SELECT * FROM count_array_elements(array [ TRUE, TRUE, FALSE, FALSE, FALSE ], TRUE);

#4


0  

Thanks to all contributors here, I learnt a few things. I am building on work of others in this thread and others in *.

感谢这里所有的贡献者,我学到了一些东西。我正在构建这个线程中的其他人和*中的其他人的工作。

I tried to create a function that will count for all the unique elements in the array.

我尝试创建一个函数来计算数组中所有唯一的元素。

I was targeting returning a json but it seems you can only return as SETOF.

我的目标是返回json,但似乎只能返回SETOF。

result of count_element_3

由于count_element_3

CREATE OR REPLACE FUNCTION count_element_3(str_array text[])
RETURNS setof text
AS
$$
DECLARE
    unique_element_array text[];
    cardinality_array int[];
    retArray text[];
BEGIN
-- Find unique items first
    unique_element_array := array(select distinct unnest(str_array));
    FOR I IN array_lower(unique_element_array, 1)..array_upper(unique_element_array, 1) 
    LOOP
    cardinality_array[I] := (select cardinality(array_positions(str_array, unique_element_array[I])));
    retArray[I] := concat(unique_element_array[I],':',cardinality_array[I]);
    END LOOP;

RETURN QUERY SELECT(retArray::text);
END;
$$
LANGUAGE plpgsql 
VOLATILE 
RETURNS NULL ON NULL INPUT;

with t1 as (SELECT
  sArray,
  c,
  coalesce(array_length( array_positions(sArray, c), 1 ),0) AS count
FROM ( VALUES
  (ARRAY['a','b','c','a','a'], 'a'),
  (ARRAY['a','b','c'], 'd')
) AS t(sArray,c)
)

select sarray, count_element_3(sarray) from t1

    sarray          count_element_3 
    text[]          text
-------------------------------------
    "{a,b,c,a,a}"   "{c:1,a:3,b:1}"
    "{a,b,c}"       "{c:1,a:1,b:1}"