JSON from SQL query with child level - sql

I have a simple query in my database:
SELECT id, name FROM users FOR JSON AUTO, ROOT('users')
This returns the following JSON:
{
"users": [
{"id": "1", "name": "John"}
{"id": "2", "name": "Mike"}
]
}
I want to have the return with the following format:
{
"users": {
"list": [
{"id": "1", "name": "John"}
{"id": "2", "name": "Mike"}
]
}
}
Can I do this on SQL level by simply changing the query?

You may try with this:
Table:
CREATE TABLE users (
id varchar(1),
[name] varchar(50)
)
INSERT INTO users
(id, [name])
VALUES
('1', 'John'),
('2', 'Mike')
Statement:
SELECT users = (SELECT id, name FROM users FOR JSON AUTO, ROOT('list'))
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
Result:
{"users":{"list":[{"id":"1","name":"John"},{"id":"2","name":"Mike"}]}}

Related

Is there an UPDATE equivalent command to SELECT json data

Is there a way to update the data retrieved from the below select (in this case, change "MS220" to something else)? It's difficult enough to do select from JSON in some cases. I'm not sure how to update just a single element.
CREATE TABLE JData (
JsonData nvarchar(max)
)
INSERT INTO JData
(JsonData)
VALUES
('[
{
"Categories": [
{
"QuerySourceNames": [
"QAsset"
],
"Id": "eceae85a-ffc6-49f4-8f6a-78ce2b4b274e",
"Name": "emsdba"
}
],
"Id": "525b4f07-0f67-43ac-8070-a0e6c1ceb1b9",
"Name": "MS220"
}
]')
SELECT
ParamName
FROM [dbo].[JData] jsonData
CROSS APPLY OPENJSON (jsonData)
WITH
(
Categories nvarchar(max) AS json,
Id uniqueidentifier,
ParamName varchar(10) '$.Name'
);
Try JSON_MODIFY() with the path '$[0].Name'
UPDATE d
SET jsonData = JSON_MODIFY(jsonData, '$[0].Name', 'New Value')
FROM [dbo].[JData] d
Results:
[
{
"Categories": [
{
"QuerySourceNames": [
"QAsset"
],
"Id": "eceae85a-ffc6-49f4-8f6a-78ce2b4b274e",
"Name": "emsdba"
}
],
"Id": "525b4f07-0f67-43ac-8070-a0e6c1ceb1b9",
"Name": "New Value"
}
]
db<>fiddle here

JSON array parsing into rows

I have JSON as below,
{
"value": [
{
"id": "123",
"createdDateTime": "2021-09-17T14:15:18Z"
},
{
"id": "124",
"createdDateTime": "2022-09-17T14:15:18Z"
}
]
}
am trying to get the output as 2 separate records and store it in clob column(values), any help would be appreciated.
values
{"id": "123","createdDateTime": "2021-09-17T14:15:18Z"}
{"id": "123","createdDateTime": "2021-09-17T14:15:18Z"}
You can use JSON_TABLE:
SELECT j.value
FROM table_name t
CROSS APPLY JSON_TABLE(
t.json_value,
'$.value[*]'
COLUMNS
value VARCHAR2(4000) FORMAT JSON PATH '$'
) j
Which, for the sample data:
CREATE TABLE table_name (json_value CLOB CHECK (json_value IS JSON));
INSERT INTO table_name (json_value)
VALUES ('{"value":[{
"id": "123",
"createdDateTime": "2021-09-17T14:15:18Z"
},
{
"id": "124",
"createdDateTime": "2022-09-17T14:15:18Z"
}]}')
Outputs:
VALUE
{"id":"123","createdDateTime":"2021-09-17T14:15:18Z"}
{"id":"124","createdDateTime":"2022-09-17T14:15:18Z"}
db<>fiddle here

Convert table to JSON array with longtext column

I'm using mariaDB 10.3, I have a table:
CREATE TABLE user(id INT NOT NULL AUTO_INCREMENT, name VARCHAR(100) NOT NULL, parameters longtext, PRIMARY KEY(id));
With rows:
INSERT INTO user VALUES (1, 'name1', '{"number": 1, "text": "some text"}'), (2, 'name2', '{"number": 2, "text": "some more text"}');
I'm trying to write query that returns the table as JSON object.
So far I have
SELECT CONCAT(
'[',
GROUP_CONCAT(JSON_OBJECT('id',id,'name',name,'parameters', parameters)),
']'
)
FROM user;
But this returns:
[
{"id": 1,
"name": "name1",
"parameters": "{\"number\": 1, \"text\": \"some text\"}"
},
{
"id": 2,
"name": "name2",
"parameters": "{\"number\": 2, \"text\": \"some more text\"}"
}
]
which is not a proper JSON. What should I change to get parameters properly formatted?
What I would like to get is:
[
{
"id": 1,
"name": "name1",
"parameters": {
"number": 1,
"text": "some text"
}
},
{
"id": 2,
"name": "name2",
"parameters": {
"number": 2,
"text": "some more text"
}
}
]
Thanks
Just JSON_COMPACT function, which's proper to MariaDB and does not exists in MySQL, might be applied for the parameters column
SELECT CONCAT(
'[',
GROUP_CONCAT(JSON_OBJECT('id',id,
'name',name,'parameters',
JSON_COMPACT(parameters))),
']'
) AS "JSON Value"
FROM user
Demo

SQL - Json query

I have tables similar to below where it has one to many mapping
DECLARE #T1 TABLE(RootId int, [Name] varchar(50))
DECLARE #T2 TABLE(Id int,RootId int, Category varchar(50))
INSERT INTO #T1
VALUES(1,'Some Name 12121'),(2,'Some Name 343434')
INSERT INTO #T2
VALUES(100,1,'Category 3333'),
(101,1,'Category 2222'),
(102,1,'Category 4444'),
(103,1,'Category 5555'),
(104,2,'Category 1111'),
(105,2,'Category 77777')
I am expecting to write query so it produce json as below format, where it had item and array of sub
[
{
"item": {
"rootId": 1,
"name": "Some Name 12121",
"sub": [
{
"id": 100,
"category": "Category 3333"
},
{
"id": 101,
"category": "Category 2222"
}
]
}
}
]
I have tried below but could not achieve the expected output
SELECT T1.RootId,T1.Name,T2.Id AS [Sub.Id],T2.Category as [Sub.Category]
FROM #T1 T1
INNER JOIN #T2 T2 ON T1.RootId = T2.RootId
FOR JSON PATH, root('item')
Is there a way to query so that it produce expected Json
All you need to do is (trivially) alias your table properly and then use AUTO instead of PATH:
SELECT T1.RootId,T1.Name,sub.Id AS Id,sub.Category as Category
FROM #T1 T1
INNER JOIN #T2 sub ON T1.RootId = sub.RootId
FOR JSON AUTO, ROOT('item');
Which outputs (after applying a format prettifier):
{
"item": [
{
"RootId": 1,
"Name": "Some Name 12121",
"sub": [
{
"Id": 100,
"Category": "Category 3333"
},
{
"Id": 101,
"Category": "Category 2222"
},
{
"Id": 102,
"Category": "Category 4444"
},
{
"Id": 103,
"Category": "Category 5555"
}
]
},
{
"RootId": 2,
"Name": "Some Name 343434",
"sub": [
{
"Id": 104,
"Category": "Category 1111"
},
{
"Id": 105,
"Category": "Category 77777"
}
]
}
]
}

SQL JSON : Nest few nodes under a custom node using sql query FOR JSON

So I have written a query that gives the output as an array of JSON objects, one of the objects is below
{
"cardType": "abc",
"createdOnDateTime": "2020-03-26",
"courseName": "course1",
"courseID": 1,
"sectionName": 1,
"studentList": [
{
"name": "student 1",
"nameLink": "0"
},
{
"name": "student 2",
"nameLink": "0"
},
{
"name": "student 3",
"nameLink": "0"
}
]
}
But I want the output as
{
"cardType": "abc",
"createdOnDateTime": "2020-03-26",
"payload" : {
"courseName": "course1",
"courseID": 1,
"sectionName": 1,
"studentList": [
{
"name": "student 1",
"nameLink": "0"
},
{
"name": "student 2",
"nameLink": "0"
},
{
"name": "student 3",
"nameLink": "0"
}
]
}
}
I have used 'For JSON Auto' phrase at the end of my Select query and as the course and student has a One-to-many relation, the student gets formatted in an array. What I want is that few nodes along with the "studentList" node array should be nested under a custom node 'payload'. How can this be achieved in SQL query using the For JSON and it's related properties?
Totally guessing here on what your data and query looks like based on what little you've given us so far. Use a subquery for studentList with for json auto then, on your outer query use for json path, without_array_wrapper.
When using for json path you can nest elements inside each other by giving them dot-separated paths, i.e.: separating parent elements from children with period (.) characters, such as the following...
create table dbo.Course (
cardType nvarchar(3),
createdOnDateTime date,
courseName nvarchar(20),
courseID int,
sectionName int
);
insert dbo.Course values
('abc', '2020-03-26', 'course1', 1, 1);
go
create table dbo.Student (
courseID int,
name nvarchar(20),
nameLink nvarchar(20)
);
insert dbo.Student values
(1, 'student 1', '0'),
(1, 'student 2', '0'),
(1, 'student 3', '0');
go
select
cardType,
createdOnDateTime,
[payload.courseName] = courseName,
[payload.courseID] = courseID,
[payload.sectionName] = sectionName,
[payload.studentList] = (
select name, nameLink
from dbo.Student S1
where S1.courseID = C1.courseID
for json auto
)
from dbo.Course C1
where courseID = 1
for json path, without_array_wrapper;
go
Which yields the result...
{
"cardType": "abc",
"createdOnDateTime": "2020-03-26",
"payload": {
"courseName": "course1",
"courseID": 1,
"sectionName": 1,
"studentList": [
{
"name": "student 1",
"nameLink": "0"
},
{
"name": "student 2",
"nameLink": "0"
},
{
"name": "student 3",
"nameLink": "0"
}
]
}
}
My query was resolved eventually, I found this really helpful video on youtube that exactly shows what I had to do. Click here for the video.
Also one more thing, this video is a very good example, but for large size data, this approach makes the query very slow.