5

I have a table where one column has an array - but stored in a text format:

mytable

id  ids
--  -------
1   '[3,4]'
2   '[3,5]'
3   '[3]'
etc ...

I want to find all records that have the value 5 as an array element in the ids column.

I was trying to achieve this by using the "string to array" function and removing the [ symbols with the translate function, but couldn't find a way.

2 Answers 2

5

You can do this: http://www.sqlfiddle.com/#!1/5c148/12

select *
from tbl
where translate(ids, '[]','{}')::int[] && array[5];

Output:

| ID |   IDS |
--------------
|  2 | [3,5] |

You can also use bool_or: http://www.sqlfiddle.com/#!1/5c148/11

with a as
(
  select id, unnest(translate(ids, '[]','{}')::int[]) as elem
  from tbl
)
select id
from a
group by id
having bool_or(elem = 5);

To see the original elements:

with a as
(
  select id, unnest(translate(ids, '[]','{}')::int[]) as elem
  from tbl
)
select id, '[' || array_to_string(array_agg(elem), ',') || ']' as ids
from a
group by id
having bool_or(elem = 5);

Output:

| ID |   IDS |
--------------
|  2 | [3,5] |

Postgresql DDL is atomic, if it's not late yet in your project, just structure your stringly-typed array to a real array: http://www.sqlfiddle.com/#!1/6e18c/2

alter table tbl
add column id_array int[];

update tbl set id_array = translate(ids,'[]','{}')::int[];

alter table tbl drop column ids;

Query:

select *
from tbl
where id_array && array[5]

Output:

| ID | ID_ARRAY |
-----------------
|  2 |      3,5 |

You can also use contains operator: http://www.sqlfiddle.com/#!1/6e18c/6

select *
from tbl
where id_array @> array[5];

I prefer the && syntax though, it directly connotes intersection. It reflects that you are detecting if there's an intersection between two sets(array is a set)

http://www.postgresql.org/docs/8.2/static/functions-array.html

1
  • Thanks a lot, its actually not that late, i will try to convince that this field gets changed to a real array, thanks a lot for the help Commented Sep 17, 2012 at 20:09
3

If you store the string representation of your arrays slightly differently, you can cast to array of integer directly:

INSERT INTO mytable
VALUES 
 (1, '{3,4}')
,(2, '{3,5}')
,(3, '{3}');

SELECT id, ids::int[]
FROM   mytable;

Else, you have to put in one more step:

SELECT (translate(ids, '[]','{}'))::int[]
FROM   mytable

I would consider making the column an array type to begin with.

Either way, you can find your row like this:

SELECT id, ids 
FROM  (
    SELECT id, ids, unnest(ids::int[]) AS elem
    FROM   mytable
    ) x
WHERE  elem = 5
2
  • 1
    agreed, though if he can edit the database structure he would be better off storing those IDs in separate fields entirely. Commented Sep 15, 2012 at 0:02
  • 1
    @sudowned: Or even in a separate table with one number per row. But we really don't have enough information to tell for sure. Commented Sep 15, 2012 at 0:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.