2

I have a table with a array column like this:

my_table
id   array
--   -----------
1    {1, 3, 4, 5}
2    {19,2, 4, 9}
3    {23,46, 87, 6}
4    {199,24, 93, 6}

And i want as result what and where is the repeated values, like this:

value_repeated    is_repeated_on
--------------    -----------
4                 {1,2}
6                 {3,4}

Is it possible? I don't know how to do this. I don't how to start it! I'm lost!

Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228
Pablo Souza
  • 863
  • 2
  • 11
  • 25

2 Answers2

4

Use unnest to convert the array to rows, and then array_agg to build an array from the ids

It should look something like this:

SELECT v AS value_repeated,array_agg(id) AS is_repeated_on FROM 
(select id,unnest(array) as v from my_table) 
GROUP by v HAVING Count(Distinct id) > 1

Note that HAVING Count(Distinct id) > 1 is filtering values that don't appear even once

Uri Goren
  • 13,386
  • 6
  • 58
  • 110
  • 1
    Note that as currently written this will show all possible values; to show only those which appear in at least two places, you need to add a `HAVING` clause, e.g. `HAVING Count(Distinct id) > 1`, or just `HAVING Count(*) > 1` if you're sure the same number will never appear twice within the same array. – IMSoP Apr 27 '15 at 13:58
3

The clean way to call a set-returning function like unnest() is in a LATERAL join, available since Postgres 9.3:

SELECT value_repeated, array_agg(id) AS is_repeated_on
FROM   my_table
     , unnest(array_col) value_repeated
GROUP  BY value_repeated
HAVING count(*) > 1
ORDER  BY value_repeated;  -- optional

About LATERAL:

There is nothing in your question to rule out shortcut duplicates (the same element more than once in the same array (like I@MSoP commented), so it must be count(*), not count (DISTINCT id).

Community
  • 1
  • 1
Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228