PostgreSQL : Use of ANY for multiple values - sql

I am trying to use the ANY function of PostgreSQL to search the value from array interger type column.
My SQL:
SELECT
*
FROM
company_employee_contacts
WHERE
corporate_complaint_type_ids = ANY(ARRAY[1,3]::integer[])
But it is giving me below error:
ERROR: operator does not exist: integer[] = integer
Can anyone tell me why I am getting this error while I am typecasting it?

because corporate_complaint_type_ids is not integer, but rather array of integers... You can't:
select '{2,3,4}'::int[] = ANY(ARRAY[1,3]::integer[]);
ERROR: operator does not exist: integer[] = integer
LINE 1: select '{2,3,4}'::int[] = ANY(ARRAY[1,3]::integer[]);
instead you can check if arrays overlap:
postgres#pond93# select '{2,3,4}'::int[] && ARRAY[1,3]::integer[];
?column?
----------
t
(1 row)
or you can check one array value against ANY(array):
postgres#pond93# select ('{2,3,4}'::int[])[1] = ANY(ARRAY[1,3]::integer[]);
?column?
----------
f
(1 row)

Related

PostgreSQL returning NULL as a row in case query returns empty

I have a generic code which is trying to access field values after query returns.
SELECT
ROUND(AVG(EXTRACT(EPOCH FROM (time::timestamp)))) as extended_time
FROM log_info
WHERE
id = 1 AND
code = 200;
However, this is returning NULL value as single row which is causing my application to crash.
for row in &con.query(query, args.as_slice()).unwrap() {
let extended_time: i32 = row.get("extended_time");
...
}
crashes with following error :-
error retrieving column "extended_time": Conversion(WasNull)
Running manually returns
extended_time
-------------
(1 row)
Without AVG query returns expected result
SELECT
EXTRACT(EPOCH FROM (time::timestamp)) as extended_time
FROM log_info
WHERE
id = 1 AND
code = 200;
extended_time
-------------
(0 rows)
An i32 can't be empty. You should use an Option as your query can return NULL:
let extended_time: Option<i32> = row.get("extended_time");

how to check a value of a key is true in postgres jsonb query

For example my table is :
CREATE TABLE mytable (
id bigint NOT NULL,
foo jsonb
);
and it has some values :
id | foo
-----+-------
1 | "{'a':false,'b':true}"
2 | "{'a':true,'b':false}"
3 | NULL
I want to know how to check if value of a key is true , and which operator should I use?
I want something like this that can check the value :
SELECT 1
FROM mytable
WHERE
id=2
AND
foo['a'] is true
;
The syntax foo['a'] is invalid in Postgres.
If you want to access the value of a key, you need to use the ->> operator as documented in the manual
select *
from mytable
where id = 2
and foo ->> 'a' = 'true';
SELECT 1
FROM mytable
Where
id=2
AND
(foo ->> 'a')::boolean is true;
;
More correct might be
SELECT 1
FROM mytable
WHERE id=2
AND (foo -> 'a') = 'true'::JSONB;
This has the benefit of allowing postgres to make better use of any indexes you may have on your jsonB data as well as avoiding some of the ambiguity with the ->> operator that others have mentioned.
Using ->>
=> SELECT (('{"a": true}'::JSONB)->>'a') = 'true' as result;
result
--------
t
(1 row)
=> SELECT (('{"a": "true"}'::JSONB)->>'a') = 'true' as result;
result
--------
t
(1 row)
Using ->
=> SELECT (('{"a": "true"}'::JSONB)->'a') = 'true'::JSONB as result;
result
--------
f
(1 row)
=> SELECT (('{"a": true}'::JSONB)->'a') = 'true'::JSONB as result;
result
--------
t
(1 row)
Note: This is the same as Tamlyn's answer, but with an included example of how to compare against a JSONB true.
To get the text value of a key use ->> (double head) and to get the json or jsonb value use -> (single head).
Be careful because the text representations of JSON boolean value true and string value "true" are both true.
tamlyn=# select '{"a":true}'::json->>'a' bool, '{"a":"true"}'::json->>'a' str;
bool | str
------+------
true | true
(1 row)
In your case you probably want ->.
tamlyn=# select '{"a":true}'::json->'a' bool, '{"a":"true"}'::json->'a' str;
bool | str
------+--------
true | "true"
(1 row)
Get the JSON object field, cast to boolean and do a regular SQL where clause:
select *
from mytable
where (foo -> 'a')::boolean is true;

How can I use arrayExists function when the array contains a null value?

I have a nullable array column in my table: Array(Nullable(UInt16)). I want to be able to query this column using arrayExists (or arrayAll) to check if it contains a value above a certain threshold but I'm getting an exception when the array contains a null value:
Exception: Expression for function arrayExists must return UInt8, found Nullable(UInt8)
My query is below where distance is the array column:
SELECT * from TracabEvents_ArrayTest
where arrayExists(x -> x > 9, distance);
I've tried updating the comparison in the lambda to "(isNotNull(x) and x > 9)" but I'm still getting the error. Is there any way of handling nulls in these expressions or are they not supported yet?
Add a condition to filter rows with empty list using notEmpty and assumeNotNull for x in arrayExists.
SELECT * FROM TracabEvents_ArrayTest WHERE notEmpty(distance) AND arrayExists(x -> assumeNotNull(x) > 9, distance)

Checking if a map or array is empty in Presto?

How do I check if a map has no keys in Presto? If I have a way to check if an array is empty, I can use the map_keys function to determine if the map is empty.
You can use the cardinality function: https://prestodb.io/docs/current/functions/array.html#cardinality
select cardinality(array[]) = 0;
_col0
-------
true
(1 row)
To check array is empty just compare it with = array[].
Example:
presto> select (map_keys(map(array[], array[])) = array[]) as is_empty;
is_empty
----------
true
(1 row)
Likewise, to check if a map is empty just compare it with = map().
Example:
presto> select (map(array[], array[]) = map()) as is_empty;
is_empty
----------
true
(1 row)

postgresql, jsonb field, array append via jsonb_set and jsonb_array_length

I have postgresql with jsonb field that always contains array.
I need to append new values to that array or update already existing values by index.
Looks like jsonb_set function meet my requirements. And for append new element i just need to max array index and update element with it.
But i have a trouble doing this. Lets make it step by step.
We have table campaigns with jsonb field team_members.
select id, jsonb_set(team_members, '{0}', '{"name" : "123"}') from campaigns;
id | jsonb_set
-----+-------------------
102 | [{"name": "123"}]
Okay great, if set path '{0}' statically everything works.
Lets do that dynamically
SQL for getting array length (it is our index for append)
select '{' || jsonb_array_length(team_members) || '}'::text from campaigns;
?column?
----------
{0}
Getting all together
select jsonb_set(team_members, '{' || jsonb_array_length(team_members) || '}', '{"name" : "123"}') from campaigns;
ERROR: function jsonb_set(jsonb, text, unknown) does not exist
LINE 1: select jsonb_set(team_members, '{' ||
jsonb_array_length(tea...
^ HINT: No function matches the given name and argument types. You might
need to add explicit type casts.
My question is - how can i get rid of this error ? What i'm doing wrong ?
Thanks in advance.
something like this?..
t=# with jpath as (select concat('{',0,'}')::text[] path) select jsonb_set('[]'::jsonb,path,'{"name": "123"}'::jsonb) from jpath;
jsonb_set
-------------------
[{"name": "123"}]
(1 row)
In your case should be like:
select
jsonb_set(
team_members
, concat('{',jsonb_array_length(team_members),'}')::text[]
, '{"name" : "123"}'
)
from campaigns;