How to search through in JSON array on SQL - mysql

I'm using MySQL 5.6.43 and trying to search through in JSON array in a table. My JSON in MySQL database is like this:
[
{
"Name": "AAA",
"CountryCode": "AFG",
"District": "Kabol",
"Population": 1780000
},
{
"Name": "BBB",
"CountryCode": "AFG",
"District": "Qandahar",
"Population": 237500
},
{
"Name": "CCC",
"CountryCode": "USD",
"District": "Qandahar",
"Population": 237500
}
]
I want to take the just AFG CountryCode's. So my result should be like this:
[
{
"Name": "AAA",
"CountryCode": "AFG",
"District": "Kabol",
"Population": 1780000
},
{
"Name": "BBB",
"CountryCode": "AFG",
"District": "Qandahar",
"Population": 237500
}
]
How can I achieve that?

SELECT test.data, JSON_ARRAYAGG(JSON_OBJECT('Name',jsontable.Name,
'CountryCode',jsontable.CountryCode,
'District',jsontable.District,
'Population',jsontable.Population)) filtered
FROM test,
JSON_TABLE(test.data,
'$[*]' COLUMNS (Name VARCHAR(255) PATH '$.Name',
CountryCode VARCHAR(255) PATH '$.CountryCode',
District VARCHAR(255) PATH '$.District',
Population VARCHAR(255) PATH '$.Population')) jsontable
WHERE jsontable.CountryCode = 'AFG'
GROUP BY test.data;
fiddle
In MySQL 5.6 you must use string functions - JSON is not implemented in this version yet:
SELECT CONCAT('[', GROUP_CONCAT('{', SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(test.data, '}', nums.num), '}', -1), '{', -1), '}'), ']') filtered
FROM test
CROSS JOIN (SELECT 1 num UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) nums
WHERE LOCATE('"CountryCode":"AFG"', SUBSTRING_INDEX(SUBSTRING_INDEX(REPLACE(test.data, ' ', ''), '}', nums.num), '}', -1))
GROUP BY test.data
fiddle
If source array may contain more than 4 objects per value then expand nums subquery.
Restriction: Neither key nor value to be searched must contain a space.

Related

json_search and json_remove in mysql

notice
[
{
"date": "2022. 10. 16.",
"type": 3,
"title": "friend",
"content": "JJ friend",
"parameter": "test"
},
{
"date": "2022. 10. 16.",
"type": 3,
"title": "friend",
"content": "testtest friend",
"parameter": "test1"
}
]
I wanna search and remove in json {"date": "2022. 10. 16.","type": 3,"title": "friend","content": "testtest friend","parameter": "test1"} where id = 'test2'
There's a separate column for the ID.
update UserTable set notice = json_remove(notice, json_search(notice, 'one',
'{"date": "2022. 10. 16.","type": 3,"title": "friend","content": "testtest friend","parameter": "test1"}')) where id = 'test2'";
SELECT JSON_ARRAYAGG(jsonvalue)
FROM src_table
CROSS JOIN JSON_TABLE(src_table.notice,
'$[*]' COLUMNS (jsonvalue JSON PATH '$')) jsontable
WHERE jsonvalue <> CAST('{"date": "2022. 10. 16.","type": 3,"title": "friend","content": "testtest friend","parameter": "test1"}' AS JSON)

Retrieve JSON from sql

My json format in one of the sql columns "jsoncol" in the table "jsontable" is like below.
Kindly help me to get this data using JSON_QUERY or JSON_VALUE
Please pay attention to the brackets and double quotes in the key value pairs...
{
"Company": [
{
"Info": {
"Address": "123"
},
"Name": "ABC",
"Id": 999
},
{
"Info": {
"Address": "456"
},
"Name": "XYZ",
"Id": 888
}
]
}
I am trying to retrieve all the company names using sql query. Thanks in advance
You can use:
SELECT j.name
FROM table_name t
CROSS APPLY JSON_TABLE(
t.value,
'$.Company[*]'
COLUMNS(
name VARCHAR2(200) PATH '$.Name'
)
) j
Which, for the sample data:
CREATE TABLE table_name (
value CLOB CHECK (value IS JSON)
);
INSERT INTO table_name (value)
VALUES ('{
"Company": [
{
"Info": {
"Address": "123"
},
"Name": "ABC",
"Id": 999
},
{
"Info": {
"Address": "456"
},
"Name": "XYZ",
"Id": 888
}
]
}');
Outputs:
NAME
ABC
XYZ
db<>fiddle here
You can easily use JSON_TABLE() function for this case rather provided the DB version is at least 12.1.0.2 such as
SELECT name
FROM jsontable,
JSON_TABLE(jsoncol,
'$' COLUMNS(NESTED PATH '$."Company"[*]'
COLUMNS(name VARCHAR2 PATH '$."Name"')))
Demo

How do you use JSON_QUERY with null json array inside of json object?

SELECT JSON_query([json], '$') from mytable
Returns fine the contents of [json] field
SELECT JSON_query([json], '$.Guid') from mytable
Returns null
SELECT JSON_query([json], '$.Guid[1]') from mytable
Returns null
I've also now tried:
SELECT JSON_query([json], '$[1].Guid')
SELECT JSON_query([json], '$[2].Guid')
SELECT JSON_query([json], '$[3].Guid')
SELECT JSON_query([json], '$[4].Guid')
and they all return null
So I'm stuck as to figuring out how create the path to get to the info. Maybe SQL Server json_query can't handle the null as the first array?
Below is the string that is stored inside of the [json] field in the database.
[
null,
{
"Round": 1,
"Guid": "15f4fe9d-403c-4820-8e35-8a8c8d78c33b",
"Team": "2",
"PlayerNumber": "78"
},
{
"Round": 1,
"Guid": "8e91596b-cc33-4ce7-bfc0-ac3d1dc5eb67",
"Team": "2",
"PlayerNumber": "54"
},
{
"Round": 1,
"Guid": "f53cd74b-ed5f-47b3-aab5-2f3790f3cd34",
"Team": "1",
"PlayerNumber": "23"
},
{
"Round": 1,
"Guid": "30297678-f2cf-4b95-a789-a25947a4d4e6",
"Team": "1",
"PlayerNumber": "11"
}
]
You need to follow the comments below your question. I'll just summarize them:
Probably the most appropriate approach in your case is to use OPENJSON() with explicit schema (the WITH clause).
JSON_QUERY() extracts a JSON object or a JSON array from a JSON string and returns NULL. If the path points to a scalar JSON value, the function returns NULL in lax mode and an error in strictmode. The stored JSON doesn't have a $.Guid key, so NULL is the actual result from the SELECT JSON_query([json], '$.Guid') FROM mytable statement.
The following statements provide a working solution to your problem:
Table:
SELECT *
INTO Data
FROM (VALUES
(N'[
null,
{
"Round": 1,
"Guid": "15f4fe9d-403c-4820-8e35-8a8c8d78c33b",
"Team": "2",
"PlayerNumber": "78",
"TheProblem": "doesn''t"
},
{
"Round": 1,
"Guid": "8e91596b-cc33-4ce7-bfc0-ac3d1dc5eb67",
"Team": "2",
"PlayerNumber": "54"
},
{
"Round": 1,
"Guid": "f53cd74b-ed5f-47b3-aab5-2f3790f3cd34",
"Team": "1",
"PlayerNumber": "23"
},
{
"Round": 1,
"Guid": "30297678-f2cf-4b95-a789-a25947a4d4e6",
"Team": "1",
"PlayerNumber": "11"
}
]')
) v (Json)
Statements:
SELECT j.Guid
FROM Data d
OUTER APPLY OPENJSON(d.Json) WITH (
Guid uniqueidentifier '$.Guid',
Round int '$.Round',
Team nvarchar(1) '$.Team',
PlayerNumber nvarchar(2) '$.PlayerNumber'
) j
SELECT JSON_VALUE(j.[value], '$.Guid')
FROM Data d
OUTER APPLY OPENJSON(d.Json) j
Result:
Guid
------------------------------------
15f4fe9d-403c-4820-8e35-8a8c8d78c33b
8e91596b-cc33-4ce7-bfc0-ac3d1dc5eb67
f53cd74b-ed5f-47b3-aab5-2f3790f3cd34
30297678-f2cf-4b95-a789-a25947a4d4e6

PostgreSQL: Syntax for query nested json array

I've recently discovered the PostgreSQL can be used store JSON
before I import loads of data I need to understand how to retrieve it in particular the nested objects
This postgresql tutorial is a good starting point but doesn't really explain how to query nested json array
In the sample below I need to select the codes -> code where codes -> level: 1 (adminCode1_iso) is related to adminName1 and if it exists codes -> level: 2 is related to adminName2
CREATE TABLE gn_json (
id serial NOT NULL PRIMARY KEY,
info json NOT NULL
);
comment on table gn_json is 'How PG holds json';
insert into gn_json (info)
VALUES ('{
"adminCode2": "C3",
"codes": [
{
"code": "ENG",
"level": "1",
"type": "ISO3166-2"
},
{
"code": "CAM",
"level": "2",
"type": "ISO3166-2"
}
],
"adminCode3": "12UE",
"adminName4": "Yelling",
"adminName3": "Huntingdonshire",
"adminCode1": "ENG",
"adminName2": "Cambridgeshire",
"distance": 0,
"countryCode": "GB",
"countryName": "United Kingdom",
"adminName1": "England",
"adminCode4": "12UE085"
}',
'{
"codes": [
{
"code": "81",
"level": "1",
"type": "ISO3166-2"
}
],
"adminCode1": "63",
"distance": 0,
"countryCode": "TH",
"countryName": "Thailand",
"adminName1": "Krabi"
}');
select info ->> 'countryName' as countryName,info ->> 'countryCode' as countryCode,
info ->> 'adminName1' as adminName1, info ->> 'adminCode1' as adminCode1,
info ->> 'adminName2' as adminName2, info ->> 'adminCode2' as adminCode2,
info ->'codes->0->' -> 'code' as adminCode1_iso,
info ->'codes->1->' -> 'code' as adminCode2_iso
FROM gn_json;
Edit Expected outcome
countryname countrycode adminname1 admincode1 adminname2 admincode2 admincode1_iso admincode2_iso
United Kingdom GB England ENG Cambridgeshire C3 ENG CAM
Thailand TH Krabi 63 NULL NULL 81 NULL

SQL query to return Json including array

I have a relational database (SQL Server) with normal data.
I am trying to build something with this format:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"id": "1",
"properties": { "address": "2" },
"geometry": {
"type": "Point",
"coordinates": [36.33456, 59.523456]
}
},
{
"type": "Feature",
"id": "2",
"properties": { "address": "151" },
"geometry": {
"type": "Point",
"coordinates": [36.33456, 59.523456]
}
}]
}
So far I have written this query:
select top 10
'Feature' as [type],
m.Id as id, m.Address as 'properties.address',
'Point' as 'geometry.type',
'[' + m.location + ']' as 'geometry.coordinates'
from
Buildings m
where
m.Location is not null
and m.Location <> ''
for json path, root('features')
But what I receive in action is like:
{
"features": [{
"type": "Feature",
"id": 250343,
"properties": {
"address": "there"
},
"geometry": {
"type": "Point",
"coordinates": "[5714843008,3363769468.235179]"
}
}, {
"type": "Feature",
"id": 266306,
"properties": {
"address": "here"
},
"geometry": {
"type": "Point",
"coordinates": "[36.38449104993326,59.48238372802735]"
}
}}
How can I add "type": "FeatureCollection", before the root?
I want the coordinate part to hold an array of 2 numbers, but in my current code it is a string holding the array. How can I achieve an array?
It's difficult without test data, but I think that you can build the expected JSОN output using the following statement. You need one more FOR JSON PATH (to generate the outer JSON object) and a JSON_QUERY call (to return a JSON array of scalar values instead of text holding the array):
Table:
CREATE TABLE Buildings (
Id int,
Address varchar(100),
Location varchar(100)
)
INSERT INTO Buildings (Id, Address, Location)
VALUES
(250343, 'there', '5714843008,3363769468.235179'),
(266306, 'here', '36.38449104993326,59.48238372802735')
Statement:
SELECT
[type] = 'FeatureCollection',
[features] = JSON_QUERY((
select top 10
'Feature' as [type],
m.Id as id, m.Address as 'properties.address',
'Point' as 'geometry.type',
JSON_QUERY('[' + m.location + ']') as 'geometry.coordinates'
from
Buildings m
where
m.Location is not null
and m.Location <> ''
for json path
))
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
Result:
{
"type":"FeatureCollection",
"features":[
{
"type":"Feature",
"id":250343,
"properties":{
"address":"there"
},
"geometry":{
"type":"Point",
"coordinates":[
5714843008,
3363769468.235179
]
}
},
{
"type":"Feature",
"id":266306,
"properties":{
"address":"here"
},
"geometry":{
"type":"Point",
"coordinates":[
36.38449104993326,
59.48238372802735
]
}
}
]
}
I figured a way to build custom JSON using STUFF (GROUP_CONCAT in MySQL) and XML.
See if this works for you:
1 Answer to question 1 - Note, this is a TWO-STEP PROCESS:
a) VARIABLE TO HOLD QUERY DATA
DECLARE #QUERY_DATA varchar(8000)
b) CUSTOM QUERY TO FETCH QUERY DATA FORMATTED FOR INNER JSON METADATA (all in one line)
SET #QUERY_DATA = (
SELECT STUFF(
(
SELECT ',' + CONCAT('{"type": "Feature","id": ', m.Id, ',"properties": {"address": "', m.Address, '"},"geometry": {"type": "Point","coordinates": [', m.location, ']}}'
)
FROM
Buildings m
WHERE
m.Location is not null
and m.Location <> ''
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
+)
c) FINAL OUTPUT - Concatenate / Join your JSON
SELECT CONCAT('{ ''type'':''FeatureCollection''','','',',''FEATURES'': [ ', #QUERY_DATA, ' ] }')
2 - ANSWER TO QUESTION 2 with CONSOLIDATED solution using separated X and Y coordinates as two INTEGER Type elements
{''X'':', CAST(LEFT( m.location, CHARINDEX(',', m.location)-1) as int), ',''Y'':', cast(RIGHT( m.location, LEN( m.location)-CHARINDEX(',', m.location)) as int),'}
Therefore, when we add this together, your new query would look like the following:
a) VARIABLE TO HOLD QUERY DATA
+DECLARE #QUERY_DATA varchar(8000)
b) CUSTOM QUERY TO FETCH QUERY DATA FORMATTED FOR INNER JSON METADATA (all in one line), including splitting coordinates into two INTEGER Type elements
SET #QUERY_DATA = (
SELECT STUFF(
(
SELECT ',' + CONCAT('{"type": "Feature","id": ', m.Id, ',"properties": {"address": "', m.Address, '"},"geometry": {"type": "Point","coordinates": [ {''X'':', CAST(LEFT( m.location, CHARINDEX(',', m.location)-1) as int), ',''Y'':', cast(RIGHT( m.location, LEN( m.location)-CHARINDEX(',', m.location)) as int),'}]}}'
)
FROM
Buildings m
WHERE
m.Location is not null
and m.Location <> ''
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
+)
c) FINAL OUTPUT - Concatenate / Join your OUTER and INNER JSON
SELECT CONCAT('{ ''type'':''FeatureCollection''','','',',''FEATURES'': [ ', #QUERY_DATA, ' ] }')