【问题标题】:How to get distinct array elements with postgres?如何使用 postgres 获取不同的数组元素?
【发布时间】:2017-03-30 21:41:18
【问题描述】:

我在 postgres 中有一个包含重复值的数组。例如:

SELECT cardinality(string_to_array('1,2,3,4,4', ',')::int[]) as foo
=> "foo"=>"5"

我想获取独特的元素,例如:

SELECT cardinality(uniq(string_to_array('1,2,3,4,4', ',')::int[])) as foo
=> -- No function matches the given name and argument types. You might need to add explicit type casts.

我可以在不使用 UNNEST 的情况下在 postgres 中获取数组的唯一元素吗?

【问题讨论】:

  • UNNEST 有什么问题?使用 UNNEST,您将能够选择 DISTINCT 并完成工作..
  • intarray module中有一个特定的uniq(int[])函数,但除此之外,你必须使用unnest()

标签: arrays postgresql unique postgresql-9.4


【解决方案1】:

对于整数数组,使用intarray extension:

create extension if not exists intarray;
select cardinality(uniq(string_to_array('1,2,3,4,4', ',')::int[])) as foo

或函数

create or replace function public.array_unique(arr anyarray)
    returns anyarray
    language sql
as $function$
    select array_agg(distinct elem)
    from unnest(arr) as arr(elem) 
$function$;

对于任何数组。您可以轻松修改函数以保留数组元素的原始顺序:

create or replace function public.array_unique_ordered(arr anyarray)
    returns anyarray
    language sql
as $function$
    select array_agg(elem order by ord)
    from (
        select distinct on(elem) elem, ord
        from unnest(arr) with ordinality as arr(elem, ord)
        order by elem, ord
        ) s
$function$;

例子:

with my_data(arr) as (values ('{d,d,a,c,b,b,a,c}'::text[]))
select array_unique(arr), array_unique_ordered(arr)
from my_data

 array_unique | array_unique_ordered
--------------+----------------------
 {a,b,c,d}    | {d,a,c,b}
(1 row)

【讨论】:

  • 我最终按照您的建议完成了该功能。我觉得这不是默认的 postgres 有点令人失望。
  • 如何保持数组中元素的原始顺序?
【解决方案2】:

从@klin 接受的答案开始,我对其进行了修改,以在仅选择不同值的过程中删除空值。

create or replace function public.array_unique_no_nulls(arr anyarray)
returns anyarray
language sql
as $function$
select array_agg(distinct a)
from (
    select unnest(arr) a 
) alias
where a is not null
$function$;

【讨论】:

    【解决方案3】:

    我更喜欢这种语法(大约快 5%)

    create or replace function public.array_unique(arr anyarray)
    returns anyarray as $body$
        select array( select distinct unnest($1) )
    $body$ language 'sql';
    

    使用:

    select array_unique(ARRAY['1','2','3','4','4']);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-30
      • 1970-01-01
      相关资源
      最近更新 更多