Your key = 'article_body' is an array JSON, so you need to use index get the data.
You can try this.
Schema (MySQL v5.7)
CREATE TABLE wc_article_full_data(
full_article_json JSON
);
insert into wc_article_full_data values (
'{"article_body" : [
{
"article_desc" : "THURSDAY, Sept. 1, 2016 (HealthDay News) -- Dapagliflozin improves insulin sensitivity and increases lipid oxidation and plasma ketone concentration in patients with type 2 diabetes mellitus (T2DM), according to a study published online Aug. 25 in Diabetes Care. Giuseppe Daniele",
"links" : [{
"link_name" : "Full Text (subscription or payment may be required)"}
]}
]}');
Query #1
SELECT JSON_EXTRACT(full_article_json,'$.article_body[0].article_desc') AS descriptio
FROM wc_article_full_data;
| descriptio |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| "THURSDAY, Sept. 1, 2016 (HealthDay News) -- Dapagliflozin improves insulin sensitivity and increases lipid oxidation and plasma ketone concentration in patients with type 2 diabetes mellitus (T2DM), according to a study published online Aug. 25 in Diabetes Care. Giuseppe Daniele" |
View on DB Fiddle
If you want to get all value from article_desc which from article_body array. you can try to use* in index.
SELECT JSON_EXTRACT(full_article_json,'$.article_body[*].article_desc') AS descriptio
FROM wc_article_full_data
Answer from D-Shih on Stack OverflowYour key = 'article_body' is an array JSON, so you need to use index get the data.
You can try this.
Schema (MySQL v5.7)
CREATE TABLE wc_article_full_data(
full_article_json JSON
);
insert into wc_article_full_data values (
'{"article_body" : [
{
"article_desc" : "THURSDAY, Sept. 1, 2016 (HealthDay News) -- Dapagliflozin improves insulin sensitivity and increases lipid oxidation and plasma ketone concentration in patients with type 2 diabetes mellitus (T2DM), according to a study published online Aug. 25 in Diabetes Care. Giuseppe Daniele",
"links" : [{
"link_name" : "Full Text (subscription or payment may be required)"}
]}
]}');
Query #1
SELECT JSON_EXTRACT(full_article_json,'$.article_body[0].article_desc') AS descriptio
FROM wc_article_full_data;
| descriptio |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| "THURSDAY, Sept. 1, 2016 (HealthDay News) -- Dapagliflozin improves insulin sensitivity and increases lipid oxidation and plasma ketone concentration in patients with type 2 diabetes mellitus (T2DM), according to a study published online Aug. 25 in Diabetes Care. Giuseppe Daniele" |
View on DB Fiddle
If you want to get all value from article_desc which from article_body array. you can try to use* in index.
SELECT JSON_EXTRACT(full_article_json,'$.article_body[*].article_desc') AS descriptio
FROM wc_article_full_data
use JSON_KEYS
eg.
SELECT JSON_KEYS(full_article_json) as jsonKeys;
it will return all the keys from the json array
Videos
test_tbl:
+----+------------------+
| id | json_col |
+----+------------------+
| 2 | {"a": 2, "b": 5} |
| 3 | {"c": 3, "a": 5} |
| 4 | {"d": 1, "c": 7} |
| 5 | {"e": 1, "f": 7} |
+----+------------------+
Using JSON_TABLE in Mysql 8.0:
SELECT DISTINCT json_key FROM test_tbl,
json_table(
json_keys(json_col),
'$[*]' COLUMNS(json_key JSON PATH '$')
) t;
Results:
+----------+
| json_key |
+----------+
| a |
| b |
| c |
| d |
| e |
| f |
+----------+
Well, not the best solution but works for json data type
select distinct(json_extract(json_keys(*YOUR_VALUE*),'$[0]')) from *YOUR_TABLE*
union
select distinct(json_extract(json_keys(*YOUR_VALUE*),'$[1]')) from *YOUR_TABLE*
There is a way to solve this in SQL 5.7. I will go step by step in composing the solution. The goal is to find the strength of the knight.
I am going to use the same sample table as previous post:
create table mytable ( mycol json );
insert into mytable set mycol = '[{"Race": "Orc", "strength": 14}, {"Race": "Knight", "strength": 7}]';
First, get an array of only the races.
select json_extract(mycol, '$[*].Race') from mytable;
+----------------------------------+
| json_extract(mycol, '$[*].Race') |
+----------------------------------+
| ["Orc", "Knight"] |
+----------------------------------+
Then, search for the Knight in this array (and unquote it).
select json_unquote(json_search(json_extract(mycol, '$[*].Race'), 'one', 'Knight')) from mytable;
+------------------------------------------------------------------------------+
| json_unquote(json_search(json_extract(mycol, '$[*].Race'), 'one', 'Knight')) |
+------------------------------------------------------------------------------+
| $[1] |
+------------------------------------------------------------------------------+
Having found the index, get this element from the array.
select json_extract(mycol, json_unquote(json_search(json_extract(mycol, '$[*].Race'), 'one', 'Knight'))) from mytable;
+---------------------------------------------------------------------------------------------------+
| json_extract(mycol, json_unquote(json_search(json_extract(mycol, '$[*].Race'), 'one', 'Knight'))) |
+---------------------------------------------------------------------------------------------------+
| {"Race": "Knight", "strength": 7} |
+---------------------------------------------------------------------------------------------------+
Then get the strength of this element.
select json_extract(json_extract(mycol, json_unquote(json_search(json_extract(mycol, '$[*].Race'), 'one', 'Knight'))), '$.strength') as strength from mytable;
+----------+
| strength |
+----------+
| 7 |
+----------+
You can repeat this on other fields to create other columns.
You're essentially meaning to apply selection and projection to the array elements and object fields of your JSON document. You need to do something like a WHERE clause to select a "row" within the array, and then do something like picking one of the fields (not the one you used in your selection criteria).
These are done in SQL using the WHERE clause and the SELECT-list of columns, but doing the same with JSON isn't something you can do easily with functions like JSON_SEARCH() and JSON_CONTAINS().
The solution MySQL 8.0 provides is the JSON_TABLE() function to turn a JSON document into a virtual derived table — as though you had defined conventional rows and columns. It works if the JSON is in the format you describe, an array of objects.
Here's a demo I did by inserting your example data into a table:
create table mytable ( mycol json );
insert into mytable set mycol = '[{"Race": "Orc", "strength": 14}, {"Race": "Knight", "strength": 7}]';
SELECT j.* FROM mytable, JSON_TABLE(mycol,
'$[*]' COLUMNS (
race VARCHAR(10) PATH '$.Race',
strength INT PATH '$.strength'
)
) AS j;
+--------+----------+
| race | strength |
+--------+----------+
| Orc | 14 |
| Knight | 7 |
+--------+----------+
Now you can do things you normally do with SELECT queries, like selection and projection:
SELECT j.strength FROM mytable, JSON_TABLE(mycol, '$[*]'
COLUMNS (
race VARCHAR(10) PATH '$.Race',
strength INT PATH '$.strength'
)
) AS j
WHERE j.race = 'Orc'
+----------+
| strength |
+----------+
| 14 |
+----------+
This has a couple of problems:
You need to do this every time you query the JSON data, or else create a VIEW to do it.
You said you don't know the attribute fields, but to write a JSON_TABLE() query, you must specify the attributes you want to search and project in your query. You can't use this for totally undefined data.
I've answered quite a number of similar questions about using JSON in MySQL. I've observed that when you want to do this sort of thing, treating a JSON document like a table so you can apply condition in the WHERE clause to fields within your JSON data, then all your queries get a lot more difficult. Then you start feeling like you would have been better off spending a few minutes to define your attributes so you could write simpler queries.