Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get distinct array elements with postgres?

I have an array with duplicate values in postgres. For example:

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

I would like to get unique elements, for example:

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.

Can I get unique elements of an array in postgres without using UNNEST ?

like image 244
Benjamin Crouzier Avatar asked Nov 16 '16 15:11

Benjamin Crouzier


People also ask

How do I get unique values in PostgreSQL?

Removing duplicate rows from a query result set in PostgreSQL can be done using the SELECT statement with the DISTINCT clause. It keeps one row for each group of duplicates. The DISTINCT clause can be used for a single column or for a list of columns.

How does distinct work in PostgreSQL?

In the SELECT statement, the PostgreSQL DISTINCT clause is used to delete duplicate records from a result set. For each set of duplicates, the DISTINCT clause saves one row. PostgreSQL DISTINCT eliminates all duplicate rows and keeps just one entry for each duplicated row group.

How do you remove duplicate values from an array in SQL?

The array_unique() function removes duplicate values from an array.


2 Answers

I prefer this syntax (about 5% faster)

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

using:

select array_unique(ARRAY['1','2','3','4','4']);
like image 197
Aliday K Avatar answered Oct 11 '22 16:10

Aliday K


For integer arrays use intarray extension:

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

or the function

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$;

for any array. You can easily modify the function to preserve the original order of the array elements:

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$;

Example:

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)
like image 28
klin Avatar answered Oct 11 '22 16:10

klin