Postgresql ALL with IN - postgresql

Without using a subquery I'd like to find if all the elements in an array are equal to a subset of numbers. So instead of 1 = ALL(ARRAY[1,1,1]) I want to do something like ALL(ARRAY[1,1,1]) IN (1, 5). Is this possible without using a select statement?

You want to use the #> operator.
-- does the column contain all of
select * from test_arrays where values #> array[6, 9];
select * from test_arrays where values #> '{6, 9}'::int[];
If you want to find where any 1 value of the array is in the other array use the && operator:
-- does the column contain at-least one of
select * from test_arrays where values && array[6, 9];
select * from test_arrays where values && '{6, 9}'::int[];
I happened to write about this a couple of months ago.
http://www.philliphaydon.com/2016/05/07/postgresql-and-its-array-datatype/

Related

Query table by a value in the second dimension of a two dimensional array column

WHAT I HAVE
I have a table with the following definition:
CREATE TABLE "Highlights"
(
id uuid,
chunks numeric[][]
)
WHAT I NEED TO DO
I need to query the data in the table using the following predicate:
... WHERE id = 'some uuid' and chunks[????????][1] > 10 chunks[????????][3] < 20
What should I put instead of [????????] in order to scan all items in the first dimension of the array?
Notes
I'm not entirely sure that chunks[][1] even close to something I need.
All I need is to test a row, whether its chunks column contains a two dimensional array, that has in any of its tuples some specific values.
May be there's better alternative, but this might do - you just go over first dimension of each array and testing your condition:
select *
from highlights as h
where
exists (
select
from generate_series(1, array_length(h.chunks, 1)) as tt(i)
where
-- your condition goes here
h.chunks[tt.i][1] > 10 and h.chunks[tt.i][3] < 20
)
db<>fiddle demo
update as #arie-r pointed out, it'd be better to use generate_subscripts function:
select *
from highlights as h
where
exists (
select *
from generate_subscripts(h.chunks, 1) as tt(i)
where
h.chunks[tt.i][3] = 6
)
db<>fiddle demo

postgres array of range type check include

Is there a way to check if array of range includes another array of range in postgres
create table t(f int4range[])
insert into t values(array[int4range(1, 3), int4range(5,8)]);
select * from t where myincludes(f, array[int4range(1,2), int4range(5,6)]
this SQL will return the data:
| [NumericRange(1, 3, '[)'), NumericRange(5, 8, '[)')] |
+------------------------------------------------------+
the array length might not be the same. but the range won't have overlap.
One way I can come up with is loop over the arguments then check if there is any range that contains the argument like this:
for i in arguments:
contains := false
for j in data:
if j contains i:
contains = true
break // check the next argument
if contains == false:
return false
But I wonder if there another way I can achieve this.
Thanks!
You can unnest() and join both arrays. If there is a pair in that result, where one range doesn't contain the other, to check this you can use the #> operator, it's not a match. You can use a NOT EXISTS in the outer queries WHERE clause to check, that no such pair exists.
SELECT *
FROM t
WHERE NOT EXISTS (SELECT *
FROM unnest(f) WITH ORDINALITY un1(f, o)
FULL JOIN unnest(array[int4range(1,2), int4range(5,6)]) WITH ORDINALITY un2(f, o)
ON un2.o = un1.o
WHERE NOT coalesce(un1.f #> un2.f, false));

Postgres select rows where ANY in a given array = ANY in column array

In Postgres, I need to select all rows where any value in an array (passed as variable) is equal to any value in the column (that is also an array). This means something like this:
SELECT *
from table
where ANY (value_in_an_array_variable) = ANY (value_in_a_column_array);
If there is no direct way what's the best alternative?
You are looking for the overlaps ("have elements in common") operator:
select *
from some_table
where array_column && array[1,2,3];

Is it possible to combine the ANY and BETWEEN operator

I need to check if any value in a Postgres array is between a given range. Something like this:
SELECT * FROM my_table WHERE ANY(my_array) BETWEEN 50 AND 60;
I realize that I can't actually do this, since the ANY operator must always be on the right side of the expression. Does anyone know of a convenient work around for doing something like this?
You can use range types, specifically the range membership operator #>:
SELECT * FROM my_table WHERE '[50,60]'::int4range #> ANY(my_array);
If you need to pull the range bounds from a column or parameter, the range constructor function might suit you better:
SELECT * FROM my_table WHERE int4range(a,b,'[]') #> ANY(my_array);
if you need range
select array_agg(q.arr) arr
from (
select unnest(ARRAY[1,2,3,4,5,6,7,8,9,10]) arr
) q
where q.arr between 3 and 5

searching an element in an array without a loop in postgresql

Im writing a query for searching an element in an array. Search using "for" loop is not efficient because my array is having a lot of elements. Because of this the query is taking lot of time to execute. So can any one say how to search an element in an array without "for" loop which should be faster. I have to get the index on searching
Thanks,
Karthika
Use the ANY operator:
where 1 = ANY (array_column)
That will return all rows where array_column contains the value 1 at least once. If you want to check for multiple values, see Clodoaldo's answer.
If you create an index on that column, this should be very fast. Something like this:
create index on the_table using gin (the_array_column);
The following is inspired by the solution shown here: Finding the position of a value in PostgreSQL arrays
with sample_data (pk_column, array_data) as (
values
(1, array[1,2,3,4,5]),
(2, array[7,8,9,11]),
(3, array[5,4,3,2,1]),
(4, array[10,9,8,1,4,6]),
(5, array[7,8,9])
)
select *
from (
select pk_column,
unnest(array_data) as value,
generate_subscripts(array_data, 1) as array_index
from sample_data
where 1 = any(array_data)
) t
where value = 1
The inner where will reduce the total work that needs to be done to only those rows that actually contain the value. The outer query will then "explode" the array to get the value's index. But using the function shown in the linked question might actually be what you are after.
Check the contains operator #>
select array[1,2] #> array[1];
?column?
----------
t
http://www.postgresql.org/docs/current/static/functions-array.html