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
Related
I'm trying to get the data within the Rule column. It has a value in JSON format. I'm trying to construct the query to get the part which says "value":8.
Column name: Rule.
JSON within column:
{"element":[{"maxDiscount":0,"minAmount":100,"total":{"type":"ABSOLUTE_OFF","value":8}}]}
I'm stuck with this query:
select id, rule->>'$."total"' from table A
order by id desc;
My desired output is...
ID | Value
1A | 8
You may try using the JSON path $.element[0].total.value here:
SELECT
id,
JSON_EXTRACT(rule, '$.element[0].total.value') AS val
FROM tableA
ORDER BY id DESC;
Is this what you are looking for?
rule ->> "$.element[0].total.value"
This gives you the value attribute for the total entity that is the first element in the element array.
This can also be expressed:
json_extract(rule, "$.element[0].total.value")
Demo on DB Fiddle:
select rule ->> "$.element[0].total.value" res
from (
select cast('{"element":[{"maxDiscount":0,"minAmount":100,"total":{"type":"ABSOLUTE_OFF","value":8}}]}' as json) rule
) t
| res |
| :-- |
| 8 |
I'm still pretty new to handling JSON fields in MySQL. All the solutions I've come across deal with objects that have key/values; unable to find one that handles JSON arrays.
Anyways, what I want to do is to be able to select all rows where the interestIds contain 2 in them. How do I do that? Thanks.
Users table
+----+-------------+
| id | interestIds |
+----+-------------+
| 1 | [1, 2] |
| 2 | [3, 2] |
| 3 | [2, 4] |
+----+-------------+
Sample test query:
SET #userId = 2;
SELECT * FROM Users
WHERE #userId IN JSON_CONTAINS(#user, interestIds, '$[1]');
I am confused as how to use the JSON_* functions; not sure what to put for the 3rd parameter...
You can use the following solution, using JSON_CONTAINS:
SELECT *
FROM Users
WHERE JSON_CONTAINS(interestIds, '2') = 1;
The third (optional) paramater path gives you the posibility to use this function only on a specific part of your JSON value. So the following example checks if 2 is the second value of the array:
SELECT *
FROM test
WHERE JSON_CONTAINS(interestIds, '2', '$[1]') = 1;
demo on dbfiddle.uk
Use JSON_SEARCH which returns path to element you are searching, or null if not found:
SELECT *
FROM users
WHERE JSON_SEARCH(interestids, 'one', '2') IS NOT NULL
Live Demo
If you're storing many-to-many relationship using simple JSON array, there are better ways to do it. Consider creating user_interest table and doing it the right and simpler way. That is if your JSON actually looks like you have shown us and does not contain dynamic key-value pairs.
SQL> select id
from users
where JSON_CONTAINS(interestIds, "2","$");
+----+
| id |
+----+
| 1 |
| 2 |
| 3 |
+----+
3 rows in set (0.0015 sec)
Wrap your select to JSON_ARRAYAGG
Like:
SELECT JSON_ARRAYAGG(JSON_OBJECT(....)) FROM table....
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.
I have a table called slices with some simple json objects that looks like this:
id | payload | metric_name
---|---------------------------------------|------------
1 | {"a_percent":99.97,"c_percent":99.97} | metric_c
2 | {"a_percent":98.37,"c_percent":97.93} | metric_c
many records of this. I am trying to get this:
a_percent | c_percent
----------|----------
99.97 | 99.97
98.37 | 97.93
I am creating the type and using json_populate_recordset along with json_agg in the following fashion:
CREATE TYPE c_history AS(
"a_percent" NUMERIC(5, 2),
"c_percent" NUMERIC(5, 2)
);
SELECT * FROM
json_populate_recordset(
NULL :: c_history,
(
SELECT json_agg(payload::json) FROM slices
WHERE metric_name = 'metric_c'
)
);
The clause select json_agg(...) by itself produces a nice array of json objects, as expected:
[{"a_percent":99.97,"c_percent":99.97}, {"a_percent":98.37,"c_percent":97.93}]
But when I run it inside json_populate_recordset, I get Error : ERROR: must call json_populate_recordset on an array of objects.
What am I doing wrong?
This is a variant of #TimBiegeleisen's solution with the function json_populate_record() used in a from clause:
select id, r.*
from slices,
lateral json_populate_record(null::c_history, payload) r;
See rextester or SqlFiddle.
You don't need to use json_agg, since it appears you want to get the set of a_percent and c_percent values for each id in a separate record. Rather just call json_populate_recordset as follows:
SELECT id, (json_populate_record(null::c_history, payload)).* FROM slices
I have a table that looks like this
+------+------------------------------------+
| id | details |
+------+------------------------------------+
| 1 | {"price":"24.99","currency":"USD"} |
+------+------------------------------------+
Is it possible to, with a single MySQL select statement, obtain the value of price 24.99?
Yes, you can using JSON_EXTRACT
It probably should be like:
SELECT JSON_EXTRACT(details, "$.price")
FROM table_name
or another form:
SELECT details->"$.price"
FROM table_name
(I don't have MySql to test it)
Note that the price in your JSON stored as a string, not a number and you probably would want to cast it to a DECIMAL.