Mysql JSON output using json_object - mysql

I have been hacking at this for days now and just cannot get the final piece of the puzzle working....
The problem seems to get a nested object with 2 nested objects at the same level?
I need to get an output as follows:
{
"Id": "19115",
"ClassScheduleId": "2143",
"MaxCapacity": "30",
"WebCapacity": "20",
"TotalBooked": "0",
"TotalBookedWaitlist": "0",
"WebBooked": "0",
"SemesterId": null,
"IsCanceled": "0",
"Substitute": "0",
"Active": "1",
"IsWaitlistAvailable": "0",
"IsEnrolled": "0",
"HideCancel": "0",
"IsAvailable": "0",
"StartDateTime": "2021-09-06T09:15:00+02:00",
"EndDateTime": "2021-09-06T10:15:00+02:00",
"LastModifiedDateTime": "2021-09-07T02:35:21+02:00",
"StaffId": "100000237",
"BookingStatus": "PaymentRequired",
"VirtualStreamLink": null,
"ClassDescription": {
"Id": "257",
"Active": "0",
"Description": "<div>Designed to burn calories while toning and lengthening, this challenging class mixes intense, high-impact cardio and plyometric training with full body conditioning and yoga. Using popular and motivating music, this fast-paced, high energy class will help create that long and lean look. No class is ever the same to ensure progressive results</div>",
"LastUpdated": "2021-08-17T15:31:21+02:00",
"Name": "Bottoms Up",
"Notes": "",
"Prereq": "",
"Program": {
"Id": "26",
"Name": "Classes",
"ScheduleType": "Class",
"CancelOffset": "0"
},
"SessionType": {
"Id": "207",
"Type": "All",
"Name": "Spinning",
"NumDeducted": "1",
"ProgramId": "26"
}
}
}
My last attempt, which I think is "close" is just not working and throwing an error :-(
SELECT json_arrayagg(
json_object(
'ClassScheduleId', c.ClassScheduleId,
'MaxCapacity', c.MaxCapacity,
'WebCapacity', c.WebCapacity,
'TotalBooked', c.TotalBooked,
'TotalBookedWaitlist', c.TotalBookedWaitlist,
'WebBooked', c.WebBooked,
'IsCanceled', c.IsCanceled,
'Substitute', c.Substitute,
'Active', c.Active,
'IsWaitlistAvailable', c.IsWaitlistAvailable,
'IsEnrolled', c.IsEnrolled,
'HideCancel', c.HideCancel,
'Id', c.Id,
'IsAvailable', c.IsAvailable,
'StartDateTime', c.StartDateTime,
'EndDateTime', c.EndDateTime,
'LastModifiedDateTime', c.LastModifiedDateTime,
'BookingStatus', c.BookingStatus
'ClassDescription', json_object(
'Active', cd.Active,
'Description', cd.Description,
'Id', cd.Id,
'LastUpdated', cd.LastUpdated,
'Name', cd.Name,
'Notes', cd.Notes,
'Prereq', cd.Prereq,
GROUP_CONCAT(
'Program', json_object(
'Id', p.Id,
'Name', p.Name,
'ScheduleType', p.ScheduleType,
'CancelOffset', p.CancelOffset
),
'SessionType', json_object(
'Type', st.Type,
'Id', st.Id,
'Name', st.Name,
'NumDeducted', st.NumDeducted,
'ProgramId', st.ProgramId
)
)
)
)
)
FROM Classes as c
LEFT JOIN ClassDescription as cd ON cd.Id = c.ClassDescriptionId
LEFT JOIN Program as p ON p.Id = cd.ProgramId
LEFT JOIN SessionType as st ON st.Id = cd.SessionTypeId
Any ideas where I can get better documentation or an SQL visual editor that has the capability to format/build these types of queries?
Thanks in advance for any input!

Bingo!!! Devil is always in the detail
Seems I missed the , after 'BookingStatus', c.BookingStatus and I also removed the GROUP_CONCAT!
This works perfect!
SELECT json_arrayagg(
json_object(
'ClassScheduleId', c.ClassScheduleId,
'MaxCapacity', c.MaxCapacity,
'WebCapacity', c.WebCapacity,
'TotalBooked', c.TotalBooked,
'TotalBookedWaitlist', c.TotalBookedWaitlist,
'WebBooked', c.WebBooked,
'IsCanceled', c.IsCanceled,
'Substitute', c.Substitute,
'Active', c.Active,
'IsWaitlistAvailable', c.IsWaitlistAvailable,
'IsEnrolled', c.IsEnrolled,
'HideCancel', c.HideCancel,
'Id', c.Id,
'IsAvailable', c.IsAvailable,
'StartDateTime', c.StartDateTime,
'EndDateTime', c.EndDateTime,
'LastModifiedDateTime', c.LastModifiedDateTime,
'BookingStatus', c.BookingStatus,
'ClassDescription', json_object(
'Active', cd.Active,
'Description', cd.Description,
'Id', cd.Id,
'LastUpdated', cd.LastUpdated,
'Name', cd.Name,
'Notes', cd.Notes,
'Prereq', cd.Prereq,
'Program', json_object(
'Id', p.Id,
'Name', p.Name,
'ScheduleType', p.ScheduleType,
'CancelOffset', p.CancelOffset
),
'SessionType', json_object(
'Type', st.Type,
'Id', st.Id,
'Name', st.Name,
'NumDeducted', st.NumDeducted,
'ProgramId', st.ProgramId
)
)
)
)
FROM Classes as c
LEFT JOIN ClassDescription as cd ON cd.Id = c.ClassDescriptionId
LEFT JOIN Program as p ON p.Id = cd.ProgramId
LEFT JOIN SessionType as st ON st.Id = cd.SessionTypeId

Related

Is such a result possible with a query from an SQL database?

I want to fire a query to get such a result:
[{
id: 1,
brandName: "x"
brandModels: [
{id: 1, modelName: "abc", createdAt: "yyyy-mm-dd"},
{id: 2, modelName: "def", createdAt: "yyyy-mm-dd"},
]
},
{
id: 2,
brandName: "y"
brandModels: [
{id: 4, modelName: "ghi", createdAt: "yyyy-mm-dd"},
{id: 5, modelName: "jkl", createdAt: "yyyy-mm-dd"},
]
}]
Tables Schema
BrandsTable
{id, brandName, brand_id}
ModelsTable
{id, modelName, createdAt}
I guess it's not possible like that? I don't have any experience with text-based databases, but I can well imagine that this can be achieved with a MongoDB. Because ultimately I want to have a js object at the end of the day.
Here's an example but I have not tested it:
SELECT JSON_ARRAYAGG(
JSON_OBJECT(
'id', b.id,
'brandName', b.brandName,
'brandModels', m.modelArray
)
) AS joined_result
FROM BrandTable AS b
JOIN (
SELECT brand_id, JSON_ARRAYAGG(
JSON_OBJECT(
'id', id,
'modelName', modelName,
'createdAt', createdAt
)
) AS modelArray
FROM ModelsTable
GROUP BY brand_id
) AS m USING (brand_id);
Note that I had to assume the ModelsTable also contains a column for brand_id, otherwise there is nothing to use in the join condition.
Read documentation for JSON_OBJECT() and JSON_ARRAYAGG() for more information about how these functions work.

Use of Lateral Flatten for JSON in Snowflake

I have the following JSON as a variant field in snowflake. I get NULLS when querying the data as shown below - -
create or replace table car_sales
(
src variant
)
as
select parse_json(column1) as src
from values
('{
"MyData": {
"DataID": "16784",
"EmpFirstName": "Jenny",
"EmpLastName": "Test1",
"Description": "My Company Data",
"Assignment": [
{
"AssignentId": "1077",
"AssignentName": "Multi Location",
"AssignentDescription": "usa",
},
],
"salary": 21557
},
"Update": true
}') v;
When I query the data I get Nulls -
select value:AssignentId::string as "1ProductName"
from car_sales,
lateral flatten(input => src:Assignment);
Output is NULL
Can you help to troubleshoot why this is happening?
Try adding the MyData qualifier in the lateral flatten:
with car_sales(src) as (
select
parse_json(column1) as src
from
values
(
'{ "MyData": {
"DataID": "16784",
"EmpFirstName": "Jenny",
"EmpLastName": "Test1",
"Description": "My Company Data",
"Assignment": [
{
"AssignentId": "1077",
"AssignentName": "Multi Location",
"AssignentDescription": "usa",
},
],
"salary": 21557
}, "Update": true }'
)
)
select
value:AssignentId::string as "1ProductName"
from
car_sales,
lateral flatten(input => src:MyData:Assignment);
1ProductName
1077
You are trying to access the child node directly. Specify the parent node as well
select value:AssignentId::string as "1ProductName"
from car_sales,
lateral flatten(input => src:MyData:Assignment);
input => src:Assignment
should be
input => src:MyData:Assignment
Here is the query to read values for each key
select src:MyData.DataID::string as "DataID"
, src:MyData.EmpFirstName::string as "EmpFirstName"
, src:MyData.EmpLastName::string as "EmpLastName"
, src:MyData.Description::string as "Description"
, value:AssignentId::string as "AssignentId/1ProductName"
, value:AssignentName::string as "AssignentName"
, value:AssignentDescription::string as "AssignentDescription"
, src:MyData.salary::number as "salary"
, src:Update::boolean as "Update"
from car_sales,
lateral flatten(input => src:MyData:Assignment);

Customize JSON retrieved from mysql

Lets say this is my database table
id ProductID color size
1 abc red L
2 abc green M
3 abc yellow S
4 def purple L
5 def brown M
6 def pink S
Now I am fecthing data using my sql queires but in response i want my json in this structure
{
"status": true,
"message": "All Product Logs has been fetched Successfully",
"products": [
{
"id": "1",
"ProductID": "abc",
"colors": [
"red",
"green",
"yellow",
],
"sizes": [
"L",
"M",
"S",
]
},
{
"id": "2",
"ProductID": "def",
"colors": [
"purple",
"brown",
"pink",
],
"sizes": [
"L",
"M",
"S",
]
}
]
}
And this what i do but it doesn't makes sense
if ($response) {
$JSONDataArray=[];
$ColorDataArray=[];
$SizeDataArray=[];
while($row = mysqli_fetch_array($response)){
$ColorDataArray[]=array($row['color']);
$SizeDataArray[]=array($row['size']);
$JSONDataArray[]=array('productid' =>$row['productid'],'color' => $ColorDataArray,'sizes' => $SizeDataArray);
}
echo json_encode(['status'=>true,'message'=>'All Products has been fetched Successfully','products'=>$JSONDataArray]);
}
Anykind of help would be appreciated. What do u think should i change my database structure or should i change my query. I simply user Select * query without any where clause
One option is to use the JSON_ARRAYAGG function:
SELECT JSON_PRETTY(
CONCAT(
'{"status": true, ',
'"message": "All Product Logs has been fetched Successfully", ',
'"products": [',
(
SELECT
GROUP_CONCAT(`der`.`json`)
FROM (
SELECT
JSON_OBJECT(
'ProductID', `ProductID`,
'colors', JSON_ARRAYAGG(`color`),
'sizes', JSON_ARRAYAGG(`size`)
) `json`
FROM
`tbl`
GROUP BY
`ProductID`
) `der`
),
']}'
)
) `json_response`;
See dbfiddle.
Keep in mind: GROUP_CONCAT: The result is truncated to the maximum length that is given by the group_concat_max_len system variable.

json_agg() with pseudo row

CREATE TABLE content
(
code INTEGER NOT NULL
, nameid TEXT NOT NULL
)
INSERT INTO content(code, nameid) VALUES
( 0, 'Support')
, ( 1, 'Adrenaline')
, ( 2, 'Aquapark')
;
Need select all content as JSON array-object named 'content' with pseudo row with code = '' and nameid = 'All'
What i did:
1) Simple select
SELECT
json_build_object('content', (SELECT json_agg(json_build_object(
'code', s.code::TEXT
, 'nameid', s.nameid::TEXT
))
FROM content s
)
);
Result is
{
"content": [{
"code": "0",
"nameid": "Support"
},
{
"code": "1",
"nameid": "Adrenaline"
},
{
"code": "2",
"nameid": "Aquapark"
}
]
}
All fine, but how to add pseudo row?
2) Best i can did
SELECT
json_build_object('content', json_build_array(
json_build_object(
'code', ''
, 'nameid', 'All'::TEXT),
(SELECT json_agg(json_build_object(
'code', s.code::TEXT
, 'nameid', s.nameid::TEXT
))
FROM content s
))
);
Result is
{
"content": [{
"code": "",
"nameid": "All"
},
[{
"code": "0",
"nameid": "Support"
},
{
"code": "1",
"nameid": "Adrenaline"
},
{
"code": "2",
"nameid": "Aquapark"
}
]
]
}
And we have array in array, as in sql as in json, but i can not understand how to combine json_agg with pseudo row.
Use to_json() and union all:
select jsonb_build_object('content', json_agg(to_json))
from (
select to_json(c)
from (select '' as code, 'All' as nameid) c
union all
select to_json(c)
from content c
) s
Output:
{
"content": [
{
"code": "",
"nameid": "All"
},
{
"code": 0,
"nameid": "Support"
},
{
"code": 1,
"nameid": "Adrenaline"
},
{
"code": 2,
"nameid": "Aquapark"
}
]
}
The version with an alias in the derived table:
select jsonb_build_object('content', json_agg(codes))
from (
select to_json(c) as codes
from (select '' as code, 'All' as nameid) c
union all
select to_json(c)
from content c
) s

PostgreSQL JSON Query with embedded json Object

I'm new to postgres and I am having trouble finding an example of how to query the following:
{
"Skill": {
"Technical": [
{ "Name": "C#",
"Rating": 4,
"Last Used": "2014-08-21"
},
{ "Name": "ruby",
"Rating": 4,
"Last Used": "2014-08-21"
}
],
"Product": [
{ "Name": "MDM",
"Rating": 4,
"Last Used": "2014-08-21"
},
{ "Name": "UDM",
"Rating": 5,
"Last Used": "2014-08-21"
}
]
}
}
In short I struggling with understanding how to query through maps without having to be explicit about naming each key.
I have a query that does the following, though it seems a bit much to have to do...
Select 'Technical' as SkillType
, json_array_elements(ResourceDocument->'Skill'->'Technical')->>'Name' as SkillName
, json_array_elements(ResourceDocument->'Skill'->'Technical')->>'Rating' as Rating
, json_array_elements(ResourceDocument->'Skill'->'Technical')->>'Last Used' as LastUsed
FROM testdepot.Resource
UNION ALL
Select 'Product' as SkillType
, json_array_elements(ResourceDocument->'Skill'->'Product')->>'Name' as SkillName
, json_array_elements(ResourceDocument->'Skill'->'Product')->>'Rating' as Rating
, json_array_elements(ResourceDocument->'Skill'->'Product')->>'Last Used' as LastUsed
FROM testdepot.Resource
I am trying to find a way to do this in 1 query that allows containing all keys of a map.
In this case Product and Technical
Something like:
Select 'Product' as SkillType
, json_array_elements(ResourceDocument->'Skill'->*)->>'Name' as SkillName
, json_array_elements(ResourceDocument->'Skill'->*)->>'Rating' as Rating
, json_array_elements(ResourceDocument->'Skill'->*)->>'Last Used' as LastUsed
FROM testdepot.Resource
You can wrap a call to json_object_keys in a sub-query to first get the keys inside "Skill" and then use json_array_elements on the outer query over the result:
SELECT SkillType
, json_array_elements(ResourceDocument->'Skill'->SkillType)->>'Name' AS SkillName
, json_array_elements(ResourceDocument->'Skill'->SkillType)->>'Rating' AS Rating
, json_array_elements(ResourceDocument->'Skill'->SkillType)->>'Last Used' AS LastUsed
FROM (
SELECT json_object_keys(resourcedocument->'Skill') AS SkillType, ResourceDocument
FROM Resource
) t;