Why is this code giving me error (postgresql JSONB )? - sql

SELECT *
FROM goods
WHERE jsonb_exists_any(params->'sex', array[1, 2, 3, 4, 5])
ERROR: function jsonb_exists_any(jsonb, integer[]) does not exist
LINE 1: SELECT * FROM goods WHERE jsonb_exists_any(params->'sex',
ar...

Call functions that exist, jsonb_exists_any does not exist. Why did you think jsonb_exists_any existed? Was it just a typo?
SELECT *
FROM goods
WHERE jsonb_exists_any(params->'sex', array[1, 2, 3, 4, 5])
Find the functions that exist in the latest version here
I'm guessing you want this..
SELECT *
FROM goods
WHERE params->'sex' = ANY(ARRAY[1, 2, 3, 4, 5]);

Related

Why does (SHAPE).SDO_ORDINATES(1) syntax fail, but (SHAPE).ST_PointN(1) succeeds?

Oracle 18c:
In a related question, we determined:
The syntax of extracting collection elements by index is not supported
in SQL.
So a query that uses this syntax will fail: (shape).sdo_ordinates(1),
select
(shape).sdo_ordinates(1) as startpoint_x
from
(select sdo_geometry('linestring(1 2, 3 4, 5 6)') as shape
from dual)
Error:
ORA-00904: "MDSYS"."SDO_GEOMETRY"."SDO_ORDINATES": invalid identifier
Source: Why does SHAPE.SDO_ORDINATES(1) work in PL/SQL, but not in SQL?
However, I have a query that is similar (different datatype) that succeeds when I use seemingly similar syntax: (shape).st_pointn(1).
select
(shape).st_pointn(1) as startpoint
from
(select treat(st_geometry.from_wkt('Linestring(1 2, 3 4, 5 6)',26917) as st_linestring) as shape
from dual)
Result:
MDSYS.ST_POINT(MDSYS.SDO_GEOMETRY(2001, 26917, MDSYS.SDO_POINT_TYPE(1, 2, NULL), NULL, NULL))
Source: Why do we need to Treat() MDSYS.ST_GEOMETRY as ST_LINESTRING to use ST_PointN(1)?
Why does (SHAPE).SDO_ORDINATES(1) fail, but (SHAPE).ST_PointN(1) succeeds?
[TL;DR]
SDO_ORDINATES is a collection attribute of the MDSYS.SDO_GEOMETRY data type.
ST_POINTN is a member function of (a super-type of) the MDSYS.ST_LINESTRING data type.
When you use:
select sdo_geometry('linestring(1 2, 3 4, 5 6)').sdo_ordinates(1)
from dual
Then it the SQL engine processes the syntax as a call to a member function in the form of object_type.member_function(argument) and there is no SDO_ORDINATES member function of the SDO_GEOMETRY data type and the output is:
ORA-00904: "MDSYS"."SDO_GEOMETRY"."SDO_ORDINATES": invalid identifier
Because there is no SDO_ORDINATES member function on the MDSYS.SDO_GEOMETRY object.
If instead, you use:
select (sdo_geometry('linestring(1 2, 3 4, 5 6)').sdo_ordinates)(1)
from dual
Then the SQL engine processes the syntax as (object_type.collection_attribute)(index) and the output is:
ORA-03001: unimplemented feature
Because extracting collection elements is not supported in SQL.
Finally:
select treat(
st_geometry.from_wkt('Linestring(1 2, 3 4, 5 6)',26917)
as st_linestring
).st_pointn(1)
from dual
Returns an ST_LINESTRING object type and then you call the ST_POINTN member function with the argument 1. This works because there is a ST_POINTN member function declared on MDSYS.ST_CURVE which is the super-type of MDSYS.ST_LINESTRING.
You can see the object's source using:
select text
from all_source
where type = 'TYPE'
and owner = 'MDSYS'
and name = 'ST_LINESTRING'
ORDER BY line
and then, for it's parent:
select text
from all_source
where type = 'TYPE'
and owner = 'MDSYS'
and name = 'ST_CURVE'
ORDER BY line
Which includes the declaration:
MEMBER FUNCTION ST_PointN(aposition INTEGER) RETURN ST_Point DETERMINISTIC,
db<>fiddle here

how to return "sparse" json (choose a number of attributes ) from PostgreSQL

MongoDB has a way of choosing the fields of a JSON documents that are returned as a result of query. I am looking for the same with PostgreSQL.
Let's assume that I've got a JSON like this:
{
a: valuea,
b: valueb,
c: valuec,
...
z: valuez
}
The particular values may be either simple values or subobjects with further nesting.
I want to have a way of returning JSON Documents containing only the atttributes I choose, something like:
SELECT json_col including_only a,b,c,g,n from table where...
I know that there is the "-" operator, allowing eliminating specific attributes, but is there an operator that does exactly the opposite?
In trivial cases you can use jsonb_to_record(jsonb)
with data(json_col) as (
values
('{"a": 1, "b": 2, "c": 3, "d": 4}'::jsonb)
)
select *, to_jsonb(rec) as result
from data
cross join jsonb_to_record(json_col) as rec(a int, d int)
json_col | a | d | result
----------------------------------+---+---+------------------
{"a": 1, "b": 2, "c": 3, "d": 4} | 1 | 4 | {"a": 1, "d": 4}
(1 row)
See JSON Functions and Operators.
If you need a more generic tool, the function does the job:
create or replace function jsonb_sparse(jsonb, text[])
returns jsonb language sql immutable as $$
select $1 - (
select array_agg(key)
from jsonb_object_keys($1) as key
where key <> all($2)
)
$$;
-- use:
select jsonb_sparse('{"a": 1, "b": 2, "c": 3, "d": 4}', '{a, d}')
Test it in db<>fiddle.

How to run prepared Postgres query in vert.x with an IN ($1) parameter?

Given this SQL query:
SELECT * FROM users WHERE user_id IN (1, 2, 3)
with the (1, 2, 3) being a List<Int> of variable length, how can I bind the parameter with the vert.x Reactive Postgres client?
In the nodejs pg-promise client, it works like this:
await db.any('SELECT * FROM users WHERE user_id IN ($1:list)', [ [1, 2, 3] ])
Ended up changing the query, replacing user_id IN ($1) with user_id = ANY($1), binding an IntArray as as a single parameter

Extract all JSON keys

I have a JSON column j like:
{'a': 2, 'b': {'b1': 3, 'b2': 5}}
{'c': 3, 'a': 5}
{'d': 1, 'c': 7}
How can I get all distinct (top-level) key names from Presto? I.e. I something like
select distinct foo(j)
To return
['a', 'b', 'c', 'd']
(note that in this instance I'm not too concerned with the nested keys)
Presto documentation doesn't have any function that explicitly fits the bill. The only thing that looks close is mention of JSONPath syntax, but even this seems to be inaccurate. At least one of the following should return something but all failed in Presto for me:
select json_extract(j, '$.*')
select json_extract(j, '$..*')
select json_extract(j, '$[*]')
select json_extract(j, '*')
select json_extract(j, '..*')
select json_extract(j, '$*.*')
Further, I suspect this will return the values, not the keys, from j (i.e., [2, 3, 5, 3, 5, 1, 7]).
You can
extract JSON top-level keys with map_keys(cast(json_column as map<varchar,json>))
later "flatten" the key collections using CROSS JOIN UNNEST
then you can SELECT DISTINCT to get distinct top-level keys.
Example putting this together:
presto> SELECT DISTINCT m.key
-> FROM (VALUES JSON '{"a": 2, "b": {"b1": 3, "b2": 5}}', JSON '{"c": 3, "a": 5}')
-> example_table(json_column)
-> CROSS JOIN UNNEST (map_keys(CAST(json_column AS map<varchar,json>))) AS m(key);
key
-----
a
b
c
(3 rows)

Strange Behaviour: SQL And operator with multiple IN operators

I am using multiple IN operators with AND in my sql query where clause as given below...
---
where ID in (1, 3, 234, 2332, 2123, 989) AND tag in ('wow', 'wonderful')
But surprisingly behaviour of result seems to be of OR type rather then AND type. What I mean is it is ignoring AND operator...
Can you please explain me why?
I couldn't reproduce the result using SQL Server 2008.
SELECT * FROM
(
SELECT 0 AS ID, 'wow' as Tag
) X
WHERE ID in (1, 3, 234, 2332, 2123, 989) AND tag in ('wow', 'wonderful')
Result:
No records
SELECT * FROM
(
SELECT 1 AS ID, 'wow' as Tag
) X
WHERE ID in (1, 3, 234, 2332, 2123, 989) AND tag in ('wow', 'wonderful')
Result:
ID Tag
1 wow
Check your code again.