Mysql 5.7 json column WHERE IN not working as expected - mysql

This sql returns correct result:
select * from `user` where `profile`->"$.year" IN ("2001")
But when I add more than one values
select * from `user` where `profile`->"$.year" IN ("2001", "1")
returns empty
It seems "In" statement not working as expected on JSON column in Mysql 5.7?

See documentation:
11.6 The JSON Data Type
...
Comparison and Ordering of JSON Values
...
The following comparison operators and functions are not yet
supported with JSON values:
BETWEEN
IN()
GREATEST()
LEAST()
A workaround for the comparison operators and functions just listed is
to cast JSON values to a native MySQL numeric or string data type so
they have a consistent non-JSON scalar type.
...
Try:
SELECT *
FROM `user`
WHERE CAST(`profile` -> "$.year" AS UNSIGNED) IN ("2001", "1");
See dbfiddle.

Related

How to serialize a very big query with json_arrayagg (json_object(*))

WITH
bigquery
AS
(SELECT level from dual connect by level<1000)
SELECT json_arrayagg (json_object (*))
FROM bigquery
with this code, I can serialize the result of a query. But when the query is too big. It doesn't work anymore.
Ora-40478: output value too large (maximum:4000)
The problem come from json_arrayagg(json_object(*))
because this code works
WITH
bigquery
AS
(SELECT level from dual connect by level<1000)
SELECT *
FROM bigquery
db<>fiddle
As described in the documentation, json_arrayagg returns varchar2(4000) if returning clause of this function is not specified.
JSON_agg_returning_clause
Use this clause to specify the data type of the character string returned by this function.
If you omit this clause, or if you specify VARCHAR2 but omit the size value, then JSON_ARRAYAGG returns a character string of type VARCHAR2(4000).
You need to provide clob as returning type.
WITH
bigquery
AS
(SELECT level as l from dual connect by level<1000)
SELECT json_arrayagg (
json_object (key 'l' value l)
returning clob
)
FROM bigquery
db<>fiddle here

Check if boolean value present in nested object

I have a JSON column and the data stored looks like:
{"results":{"made":true,"cooked":true,"eaten":true}}
{"results":{"made":true,"cooked":true,"eaten":false}}
{"results":{"made":true,"eaten":true,"a":false,"b":true,"c":false}, "more": {"ignore":true}}
I need to find all rows where 1+ values in $.results is false.
I tried using JSON_CONTAINS() but didn't find a way to get it to compare to a boolean JSON value, or to look at all values in $.results.
This needs to work with MySQL 5.7 but if it's not possible I will accept a MySQL 8+ answer.
I don't know the way for to search for a JSON true/false/null value using JSON functions - in practice these values are treated as string-type values during the search with JSON_CONTAINS, JSON_SEARCH, etc.
Use regular expression for the checking. Something like
SELECT id,
JSON_PRETTY(jsondata)
FROM test
WHERE jsondata REGEXP '"results": {[^}]+: false.*}';
DEMO
You could simply search the JSON_EXTRACT using the LIKE condition this way.
SELECT * FROM table1 WHERE JSON_EXTRACT(json_dict, '$.results') LIKE '%: false%';
Check this DB FIDDLE
An alternative to the pattern matching in other answers, is to extract all values from $.results and check each entry with a helper table with running numbers
SELECT DISTINCT v.id, v.json_value
FROM (
SELECT id, json_value, JSON_EXTRACT(json_value, '$.results.*') value_array
FROM json_table
) v
JOIN seq ON seq.n < JSON_LENGTH(v.value_array)
WHERE JSON_EXTRACT(v.value_array, CONCAT('$[', seq.n, ']')) = false
Here is the demo

How to select a column WHERE its values are in json arrayin MySQL

In a word, I want to
select * from test.population where Number in (1,2,3),
but in the place of (1,2,3) I want to have a function that returns json array. So that I want to have this to be working like this.
select * from test.population where Number in ('[1,2,3]')
How to put json-array into where it clause?
You can use the MEMBER OF operator:
Number member of ('[1,2,3]')
You can use JSON_SEARCH(). It is available since MySQL 5.7, whereas MEMBER OF() came with MySQL 8.0:
select * from test.population where json_search('[1,2,3]', 'one', number) is not null

How can I pass array of tuples to sql statement using json

I’m trying to make the following sql statement in a json file:
SELECT user_id
FROM users_to_users
WHERE (user_id, contact_user_id, contact_blocked) IN ?
I tried providing an array of arrays for the ? Values but that returned an error. Is there a way with json to pass an array of tuples for the inserts in the above sql statement?
Simple Example:-
Use the FIND_IN_SET function:
SELECT t.*
FROM YOUR_TABLE t
WHERE FIND_IN_SET(3, t.ids) > 0
-- all books with tags starting 'Java':
SELECT * FROM `book`
WHERE JSON_SEARCH(tags, 'one', 'Java%') IS NOT NULL;
Check This Reference which uses JSON To see the whole possible Solutions
Reference Of FIND_IN_SET Answer

How to cross join unnest a JSON array in Presto

Given a table that contains a column of JSON like this:
{"payload":[{"type":"b","value":"9"}, {"type":"a","value":"8"}]}
{"payload":[{"type":"c","value":"7"}, {"type":"b","value":"3"}]}
How can I write a Presto query to give me the average b value across all entries?
So far I think I need to use something like Hive's lateral view explode, whose equivalent is cross join unnest in Presto.
But I'm stuck on how to write the Presto query for cross join unnest.
How can I use cross join unnest to expand all array elements and select them?
Here's an example of that
with example(message) as (
VALUES
(json '{"payload":[{"type":"b","value":"9"},{"type":"a","value":"8"}]}'),
(json '{"payload":[{"type":"c","value":"7"}, {"type":"b","value":"3"}]}')
)
SELECT
n.type,
avg(n.value)
FROM example
CROSS JOIN
UNNEST(
CAST(
JSON_EXTRACT(message,'$.payload')
as ARRAY(ROW(type VARCHAR, value INTEGER))
)
) as x(n)
WHERE n.type = 'b'
GROUP BY n.type
with defines a common table expression (CTE) named example with a column aliased as message
VALUES returns a verbatim table rowset
UNNEST is taking an array within a column of a single row and returning the elements of the array as multiple rows.
CAST is changing the JSON type into an ARRAY type that is required for UNNEST. It could easily have been an ARRAY<MAP< but I find ARRAY(ROW( nicer as you can specify column names, and use dot notation in the select clause.
JSON_EXTRACT is using a jsonPath expression to return the array value of the payload key
avg() and group by should be familiar SQL.
As you pointed out, this was finally implemented in Presto 0.79. :)
Here is an example of the syntax for the cast from here:
select cast(cast ('[1,2,3]' as json) as array<bigint>);
Special word of advice, there is no 'string' type in Presto like there is in Hive.
That means if your array contains strings make sure you use type 'varchar' otherwise you get an error msg saying 'type array does not exist' which can be misleading.
select cast(cast ('["1","2","3"]' as json) as array<varchar>);
The problem was that I was running an old version of Presto.
unnest was added in version 0.79
https://github.com/facebook/presto/blob/50081273a9e8c4d7b9d851425211c71bfaf8a34e/presto-docs/src/main/sphinx/release/release-0.79.rst