I have table that holds sort json number values that i need to sort id using defined json sort number...so i have table like this:
+----+------------+-----------------+
| id | channel | sort |
+----+------------+-----------------+
| 1 | US_CH 1 | ["1", "2", "4"] |
| 4 | US_CH 4 | ["1", "2", "4"] |
| 2 | US_CH 2 | ["1", "2", "4"] |
+----+------------+-----------------+
And would like to get to get this:
+----+------------+-----------------+
| id | channel | sort |
+----+------------+-----------------+
| 1 | US_CH 1 | ["1", "2", "4"] |
| 2 | US_CH 2 | ["1", "2", "4"] |
| 4 | US_CH 4 | ["1", "2", "4"] |
+----+------------+-----------------+
So the point is to get ID sort by value of json sort values in array. I know that sort json values are not json structure but i need to get using this number because i im working channel editor that update and add channels that have 5000 records (enigma2 stb) so i need using this number because it will store small data in database and inserting and updating will be more faster.
I try using JSON_SEARCH to extract single value but i need all values so that i can use like ORDER BY JSON_EXTRACT(sort, '$[extract numbers]')
Try this:
ORDER BY LOCATE(sort, CONCAT('"', id, '"'))
Related
I have extracted a mysql json dictionary strucutre and I wish to get all the values associated with the keys alpha and beta; however I also wish to print the key too. The structure of the dictionary is:
results =
{1:
{"a": {"alpha": 1234,
"beta": 2345},
"b": {"alpha": 1234,
"beta": 2345},
"c": {"alpha": 1234,
"beta": 2345},
},
2:
{"ab": {"alpha": 1234,
"beta": 2345},
"ac": {"alpha": 1234,
"beta": 2345},
"bc": {"alpha": 1234,
"beta": 2345},
},
3:
{"abc": {"alpha": 1234,
"beta": 2345}
}
"random_key": "not_interested_in_this_value"
}
So far I have been had some succes extracting the data I wish using:
SELECT JSON_EXTRACT alpha, beta FROM results;
This gave me the alpha and beta columns; however, I ideally would like to assoicate each value with their key to get:
+-------+---------+---------+
| key | alpha | beta |
+-------+---------+---------+
| a | 1234. | 2345. |
| b | 1234. | 2345. |
| c | 1234. | 2345. |
| ab | 1234. | 2345. |
| ac | 1234. | 2345. |
| bc | 1234. | 2345. |
| abc | 1234. | 2345. |
+-------+---------+---------+
I am very new to mysql and any help is appreciated.
First of all, what you posted is not valid JSON. You can use integers as values, but you can't use integers as keys in objects. Also you have a few spurious , symbols. I had to fix these mistakes before I could insert the data into a table to test.
I was able to solve this using MySQL 8.0's JSON_TABLE() function in the following way:
select
j2.`key`,
json_extract(results, concat('$."',j1.`key`,'"."',j2.`key`,'".alpha')) as alpha,
json_extract(results, concat('$."',j1.`key`,'"."',j2.`key`,'".beta')) as beta
from mytable
cross join json_table(json_keys(results), '$[*]' columns (`key` int path '$')) as j1
cross join json_table(json_keys(json_extract(results, concat('$."',j1.`key`,'"'))), '$[*]' columns (`key` varchar(3) path '$')) as j2
where j2.`key` IS NOT NULL;
Output:
+------+-------+------+
| key | alpha | beta |
+------+-------+------+
| a | 1234 | 2345 |
| b | 1234 | 2345 |
| c | 1234 | 2345 |
| ab | 1234 | 2345 |
| ac | 1234 | 2345 |
| bc | 1234 | 2345 |
| abc | 1234 | 2345 |
+------+-------+------+
If you find this sort of query too difficult, I would encourage you to reconsider whether you want to store data in JSON.
If I were you, I'd store data in normal rows and columns, then the query would be a lot simpler and easier to write and maintain.
This is a sample database 'test' with a JSON column 'arr' containing an array of JSON objects
+----+----------------------------------------------------------+
| id | arr |
+----+----------------------------------------------------------+
| 1 | [{"name": "aman"}, {"name": "jay"}] |
| 2 | [{"name": "yash"}, {"name": "aman"}, {"name": "jay"}] |
+----+----------------------------------------------------------+
I want to use JSON_CONTAINS to know if a value exists in a specific key of an object in the array.
Here's my query :
SELECT JSON_CONTAINS(arr, '"jay"', '$[*].name') from test WHERE id=1;
I get the following error:
ERROR 3149 (42000): In this situation, path expressions may not contain the * and ** tokens or an array range.
I know that I can try using JSON_EXTRACT() for this, but what am I doing wrong here ?
Is there any way to use JSON_CONTAINS with an array of JSON objects in MySQL.
Yes, it is possible using the following syntax:
SELECT JSON_CONTAINS(arr, '{"name": "jay"}') from test WHERE id=1;
db<>fiddle demo
Example:
+-----+--------------------------------------------------------+---+
| id | arr | r |
+-----+--------------------------------------------------------+---+
| 1 | [{"name": "aman"}, {"name": "jay"}] | 1 |
| 2 | [{"name": "yash"}, {"name": "aman"}, {"name": "jay"}] | 1 |
| 3 | [{"name": "yash"}, {"name": "aman"}] | 0 |
+-----+--------------------------------------------------------+---+
You must use JSON_SEARCH:
SELECT JSON_SEARCH(arr, 'one', 'jay', NULL, '$[*].name') IS NOT NULL
FROM test
WHERE id=1;
Hey I've been searching and looking all day. Have gotten further into understanding my problem and the options. By I am at a lack of understanding.
My general issue is that I am trying to SELECT rows based on values in the JSON and order the selection by there selected values.
I have a table (elements), with two columns: Person and Tags. Tags contains a JSON array that can have multiple JSON objects inside it. Objects always have "name" and "sort".
+-------------+------------------------------------------------------------------+
| Person | tags
+-------------+------------------------------------------------------------------+
| William | [{"name": "apple", "sort": "1"}, {"name": "orange", "sort": "2"}]
| Anna | [{"name": "apple", "sort": "3"}, {"name": "orange", "sort": "1"}]
| Michael | [{"name": "apple", "sort": "2"}]
+-------------+------------------------------------------------------------------+
Ideally what I would like to do is tell the database using to SELECT * FROM elements WHERE tags (has an object where name is "apple") ORDER by (The sort value from the object where it matched);
So if I gave it "apple" it would list: William, Michael, Anna.
If I gave it "orange" it would list: Anna, William.
I have been looking into having SELECTs within SELECTs (Subqueries) but I can find the right combination with JSON. Below is the closest I have gotten, but I can tell it needs something more advanced?
SELECT *
FROM elements
WHERE JSON_SEARCH( tags, 'one', 'apple', NULL, '$[*].name' ) IS NOT NULL
This will return all the people, with apple tag, but it will not order them based on the sort.
Any suggestions are welcome, thanks in advance.
Here a "nice" Query that works for you. You only must change res.* to res.name for your query.
SELECT res.* FROM (
SELECT
SUBSTRING_INDEX( JSON_UNQUOTE (JSON_SEARCH(e.tags, 'one', 'apple')),'.',1) as idx
,e.* FROM `elements` AS e ) AS res
WHERE res.idx IS NOT NULL
ORDER BY JSON_UNQUOTE(JSON_EXTRACT(res.tags,CONCAT(res.idx,'.sort')));
SAMPLE
mysql> select * from elements;
+----+---------+-------------------------------------------------------------------+
| id | Person | tags |
+----+---------+-------------------------------------------------------------------+
| 1 | William | [{"name": "apple", "sort": "1"}, {"name": "orange", "sort": "2"}] |
| 2 | Anna | [{"name": "apple", "sort": "3"}, {"name": "orange", "sort": "1"}] |
| 3 | Michael | [{"name": "apple", "sort": "2"}] |
+----+---------+-------------------------------------------------------------------+
3 rows in set (0.00 sec)
Find apple
mysql> SELECT res.* FROM (
-> SELECT
-> SUBSTRING_INDEX( JSON_UNQUOTE (JSON_SEARCH(e.tags, 'one', 'orange')),'.',1) as idx
-> ,e.* FROM `elements` AS e ) AS res
-> WHERE res.idx IS NOT NULL
-> ORDER BY JSON_UNQUOTE(JSON_EXTRACT(res.tags,CONCAT(res.idx,'.sort')));
+----+---------+-------------------------------------------------------------------+
| id | Person | tags |
+----+---------+-------------------------------------------------------------------+
| 1 | William | [{"name": "apple", "sort": "1"}, {"name": "orange", "sort": "2"}] |
| 2 | Anna | [{"name": "apple", "sort": "3"}, {"name": "orange", "sort": "1"}] |
| 3 | Michael | [{"name": "apple", "sort": "2"}] |
+----+---------+-------------------------------------------------------------------+
3 rows in set (0.00 sec)
Find orange
mysql> SELECT res.* FROM (
-> SELECT
-> SUBSTRING_INDEX( JSON_UNQUOTE (JSON_SEARCH(e.tags, 'one', 'orange')),'.',1) as idx
-> ,e.* FROM `elements` AS e ) AS res
-> WHERE res.idx IS NOT NULL
-> ORDER BY JSON_UNQUOTE(JSON_EXTRACT(res.tags,CONCAT(res.idx,'.sort')));
+------+----+---------+-------------------------------------------------------------------+
| idx | id | Person | tags |
+------+----+---------+-------------------------------------------------------------------+
| $[1] | 2 | Anna | [{"name": "apple", "sort": "3"}, {"name": "orange", "sort": "1"}] |
| $[1] | 1 | William | [{"name": "apple", "sort": "1"}, {"name": "orange", "sort": "2"}] |
+------+----+---------+-------------------------------------------------------------------+
2 rows in set (0.01 sec)
There's a similar question here which might assist you.
You may be able to use JSON_EXTRACT however it gets complicated because you're storing an array of JSON data so you might also require a sub query.
I'll propose an alternate solution though. Have you considered restructuring your database across multiple tables instead of using a JSON blob?
You could have a table dedicated to storing the tags, something like this:
+-------------+------------------------------------------------------------------+
| tagid | name
+-------------+------------------------------------------------------------------+
| 1 | apple
| 2 | orange
| 3 | banana
+-------------+------------------------------------------------------------------+
Another table for storing the people:
+-------------+------------------------------------------------------------------+
| id | name
+-------------+------------------------------------------------------------------+
| 1 | William
| 2 | Anna
| 3 | Michael
+-------------+------------------------------------------------------------------+
And finally a table for storing the many-many relationship between people and tags. This is also where you can store the sort order:
+-------------+--------------+-----------+--------------------------------------+
| id | personid | tagid | sort
+-------------+--------------+-----------+--------------------------------------+
| 1 | 1 | 1 | 1
| 2 | 1 | 2 | 2
| 3 | 2 | 1 | 3
| 4 | 2 | 2 | 1
| 5 | 3 | 1 | 1
+-------------+--------------+-----------+---------------------------------------+
A database model that looks more like this will make complicated queries much simpler and won't require complex subqueries, just joins. It's likely to improve your ability to report on data relating to your tags, if that's something that's important to you.
I have a MySQL database column that contains JSON array encoded strings. I would like to search the JSON array where the "Elapsed" value is greater than a particular number and return the corresponding TaskID value of the object the value was found. I have been attempting to use combinations of the JSON_SEARCH, JSON_CONTAINS, and JSON_EXTRACT functions but I am not getting the desired results.
[
{
"TaskID": "TAS00000012344",
"Elapsed": "25"
},
{
"TaskID": "TAS00000012345",
"Elapsed": "30"
},
{
"TaskID": "TAS00000012346",
"Elapsed": "35"
},
{
"TaskID": "TAS00000012347",
"Elapsed": "40"
}
]
Referencing the JSON above, if I search for "Elapsed" > "30" then 2 records would return
'TAS00000012346'
'TAS00000012347'
I am using MySQL version 5.7.11 and new to querying json data. Any help would be appreciated. thanks
With MySQL pre-8.0, there is no easy way to turn a JSON array to a recordset (ie, function JSON_TABLE() is not yet available).
So, one way or another, we need to manually iterate through the array to extract the relevant pieces of data (using JSON_EXTRACT()). Here is a solution that uses an inline query to generate a list of numbers ; another classic approchach is to use a number tables.
Assuming a table called mytable with a column called js holding the JSON content:
SELECT
JSON_EXTRACT(js, CONCAT('$[', n.idx, '].TaskID')) TaskID,
JSON_EXTRACT(js, CONCAT('$[', n.idx, '].Elapsed')) Elapsed
FROM mytable t
CROSS JOIN (
SELECT 0 idx
UNION ALL SELECT 1
UNION ALL SELECT 2
UNION ALL SELECT 3
) n
WHERE JSON_EXTRACT(js, CONCAT('$[', n.idx, '].Elapsed')) * 1.0 > 30
NB: in the WHERE clause, the * 1.0 operation is there to force the conversion to a number.
Demo on DB Fiddle with your sample data:
| TaskID | Elapsed |
| -------------- | ------- |
| TAS00000012346 | 35 |
| TAS00000012347 | 40 |
Yes , you can definitely to it using JSON_EXTRACT() function in mysql.
lets take a table that contains JSON (table client_services here) :
+-----+-----------+--------------------------------------+
| id | client_id | service_values |
+-----+-----------+------------+-------------------------+
| 100 | 1000 | { "quota": 1,"data_transfer":160000} |
| 101 | 1000 | { "quota": 2,"data_transfer":800000} |
| 102 | 1000 | { "quota": 3,"data_transfer":70000} |
| 103 | 1001 | { "quota": 1,"data_transfer":97000} |
| 104 | 1001 | { "quota": 2,"data_transfer":1760} |
| 105 | 1002 | { "quota": 2,"data_transfer":1060} |
+-----+-----------+--------------------------------------+
And now lets say we want client_id for all who have quota>1 , then use this query :
SELECT
id,client_id,
JSON_EXTRACT(service_values, '$.quota') AS quota
FROM client_services
WHERE JSON_EXTRACT(service_values, '$.quota') > 1;
And hence it will result into :
+-----+-----------+-------+
| id | client_id | quota |
+-----+-----------+--------
| 101 | 1000 | 2 |
| 102 | 1000 | 3 |
| 104 | 1001 | 2 |
| 105 | 1002 | 2 |
+-----+-----------+-------+
hope this helps!
I've got several Postgres 9.4 tables that contain data like this:
| id | data |
|----|-------------------------------------------|
| 1 | {"user": "joe", "updated-time": 123} |
| 2 | {"message": "hi", "updated-time": 321} |
I need to transform the JSON column into something like this
| id | data |
|----|--------------------------------------------------------------|
| 1 | {"user": "joe", "updated-time": {123, "unit":"millis"}} |
| 2 | {"message": "hi", "updated-time": {321, "unit":"millis"}} |
Ideally it would be easy to apply the transformation to multiple tables. Tables that contain the JSON key data->'updated-time' should be updated, and ones that do not should be skipped. Thanks!
You can use the || operator to merge two jsonb objects together.
select '{"foo":"bar"}'::jsonb || '{"baz":"bar"}'::jsonb;
= {"baz": "bar", "foo": "bar"}