MySQL JSON extract values only if there value > 1 - mysql

I have the following table:
+-------------+----------------+
| id | server |
+-------------+----------------+
| 1 | ["1", "15"] |
+-------------+----------------+
I need to get only value that is grather that 1 so in above example i need to get from output only 15
I try using this:
SELECT
JSON_EXTRACT(server, "$[*]") as server
FROM streams
WHERE JSON_EXTRACT(server, "$[*]") != JSON_QUOTE('1')
AND id=1;
But i always get ["1", "15"] and need to get ["15"].

Unfortunately, you can't do this with MySQL's JSON_EXTRACT and JSON_SEARCH functions as they perform extraction and exact matching (not comparison) respectively. So, you have two options:
Normalise the table and have server values into a new column (recommended)
Fetch all the values and perform the filtering in service layer

I added this:
SELECT CASE WHEN
JSON_UNQUOTE(JSON_SEARCH(server, 'all', 1)) IS NULL THEN
JSON_REMOVE(server, '$."1"')
ELSE
JSON_REMOVE(server, JSON_UNQUOTE(JSON_SEARCH(server, 'one', 1)))
END AS server
FROM streams WHERE id=2 AND server NOT LIKE '%[]%';
Now it works but if ["1"] is only 1 in json column i get []...a added NOT LIKE '%[]%' but it prints out always []...where i need to add to get no results found from mysql?

Related

How to order by array value inside json path mysql?

I have a column in db table which is of a JSON type.
This column will store such values:
column 1: ["bmw", "opel", "audi"]
column 2: ["opel", "bwm", "audi"]
column 3: ["audi"]
the order of values is different as well as the total number but in general there is a list of valid values to be stored.
On UI, there is a table with columns which can be sorted. When user clicks on a column Car Brand, ASC, I will need to sort the output from db based on the column values I mentioned above.
I'd like to receive the following output:
1: ["audi"]
2: ["audi", "bmw", "opel"]
3: ["audi", "bmw", "opel"]
I can't seem to find the solution for this using JSON path.
Can anybody help me?
Please do not suggest to store the values in a different way, it's not me who decides this.
You can't do this in MySQL.
What Akina describes in the comment above is like this demo:
set #j = '["opel", "bwm", "audi"]';
select * from json_table(#j, '$[*]' columns (a varchar(10) path '$')) j order by a;
+------+
| a |
+------+
| audi |
| bwm |
| opel |
+------+
Then the idea is to recombine these rows into a JSON array using JSON_ARRAYAGG(). However, this doesn't work:
select json_arrayagg(a) as j from (
select * from json_table(#j, '$[*]' columns (a varchar(10) path '$')) j order by a
) as a;
+-------------------------+
| j |
+-------------------------+
| ["opel", "bwm", "audi"] |
+-------------------------+
The ORDER BY in the subquery has been factored out. MySQL thinks there's no reason to sort rows in a derived table, they should be sorted as the last step of the outer query.
https://dev.mysql.com/doc/refman/5.7/en/aggregate-functions.html#function_json-arrayagg says:
JSON_ARRAYAGG(col_or_expr)
Aggregates a result set as a single JSON array whose elements consist
of the rows. The order of elements in this array is undefined.
https://bugs.mysql.com/bug.php?id=94696 is a feature request from 2019, asking for a way to sort elements before aggregating them with JSON_ARRAYAGG(). That ticket is in a "Verified" state, meaning it has been accepted as a feature request, but it has not been implemented.
There is no solution yet in MySQL 8.0 to use JSON_ARRAYAGG() to produce an array in a specific order.
So the best you can do is fetch them as sorted rows, as I showed in the intermediate step earlier in this answer, and then combine them into an array in that order in your client application code.

How to regexp in MySql json string

Let's assume this users table:
-----------------------------------------
| id | ... | info |
-----------------------------------------
| 1 | ... | {"items":["132","136"]} |
I need to make a request to fetch users that have items with id == 136.
This following is the sql I built but it does not work and I dont understand why:
SELECT _u.id FROM users _u WHERE _u.info REGEXP '("items":)([)("136")(])'
Thank you in advance!
Here is one approach using the MySQL JSON functions:
SELECT *
FROM yourTable
WHERE JSON_SEARCH(JSON_EXTRACT(json, "$.items"), 'one', "136") IS NOT NULL;
Demo
The call to JSON_EXTRACT first extracts the JSON array under the items key. Then, we use JSON_SEARCH to try to find an element "136".
Edit:
If you are certain that the JSON to be searched would always just be one key items along with a single level JSON array, then REGEXP might be viable here:
SELECT *
FROM yourTable
WHERE json REGEXP '"items":\\[.*"136".*\\]';
Demo

Get row from mysql using specific value with regexp ( json string )

I'm storing permissions into DB with Array JSON String, and i want select them by permission specific permission. at this time I'm selecting them like this:
1 | Dog | [3,4]
2 | Cat | [33,4]
3 | Tiger | [5,33,4]
4 | wolf | [3,5]
SELECT * FROM `pages` WHERE access REGEXP '([^"])3([^"])'
it works but not as it should work. This query gives me all records which contains 3 but also it gives which contains 33. my question is how i must format my regexp to get row by specific value into json string.
p.s i have mysql 5.5 so as i know on this version json functions is not supported
If you only have numbers in the fields, you can alter your regexp to only take values where the string you are looking for (here the '3') does not have another number immediately close to it :
SELECT * FROM `pages` WHERE access REGEXP '([^"0-9])3([^"0-9])'
REGEXP '[[:<:]]3[[:>:]]'
That is, use the "word boundary" thingies.

json single value condition in sql

I have an SQL database field that contains JSON type data stored.
-----------------------------
id | tags |
-----------------------------
1 | ['cat','dog'] |
2 | ['lion','cat','dog'] |
I want to select from this table by passing where condition as cat and get all the JSON fields. How would I do this?
Use the JSON_EXTRACT function as of MySQL 5.7.8. Extract from
https://dev.mysql.com/doc/refman/5.7/en/json.html#json-paths
A JSON path expression selects a value within a JSON document.
Path expressions are useful with functions that extract parts of or modify a JSON document, to specify where within that document to operate. For example, the following query extracts from a JSON document the value of the member with the name key:
mysql> SELECT JSON_EXTRACT('{"id": 14, "name": "Aztalan"}', '$.name');
+---------------------------------------------------------+
| JSON_EXTRACT('{"id": 14, "name": "Aztalan"}', '$.name') |
+---------------------------------------------------------+
| "Aztalan" |
+---------------------------------------------------------+
Note in the example they are inline creatinng a JSON object so for you
:'{"id": 14, "name": "Aztalan"}' would actually be your column value.
JSON manipulation in MySQL is slow. I suggest that you use REGEXP.
// get all rows having "cat" value
select * from animals_tbl
where tags regexp 'cat';
// get all rows based on multiple filters
select * from animals_tbl
where tags regexp 'lion|cat';

Fetching nested JSON data in HBase using Apache Drill

I am using Apache Drill to run SQL queries on a HBase table. The value in one of the columns is:
0: jdbc:drill:schema:hbase:zk=localhost> select cast(address['street'] as varchar(20)) from hbase.students;
+------------+
| EXPR$0 |
+------------+
| {"id": 123} |
+------------+
1 row selected (0.507 seconds)
I would like to access the id field using a query. Something like:
0: jdbc:drill:schema:hbase:zk=localhost> select tbl.address['street']['id'] from hbase.students as tbl;
+------------+
| EXPR$0 |
+------------+
| null |
+------------+
As you can see, this does not work. I am run to similar queries on JSON data in a file. My question is can I query JSON data in HBase.
OK. I found the answer to this question, in case someone else has the same requirement.
The first step is to convert the HBase data to JSON using the built-in convert_from() function. A view can be created against which the queries can be run.
> create or replace view Street as select convert_from(Students.address.street, 'JSON') json from hbase.Customer;
Then, run query against the view
> select * from Street;
> select Street.json.id from Street;
You can also use a subquery to convert the data in your HBase column into JSON:
select t.json.id
from (select convert_from(Students.address.street, 'JSON') json
from hbase.Customer) t;