SQL Query to get the Json inside Json values by comma separated - sql

I have the below Json object. I need to get the task names by comma (,) separated.
{
"Model": [
{
"ModelName": "Test Model",
"Object": [
{
"ID": 1,
"Name": "ABC",
"Task" : [
{
TaskID : 1222,
Name: "TaskA"
},
{
TaskID : 154,
Name: "TaskB"
}
]
},
{
"ID": 11,
"Name": "ABCD",
"Task" : [
{
TaskID : 222,
Name: "TaskX"
},
{
TaskID : 234,
Name: "TaskY"
}
]
},
]
}]}
The expected Output should be in the below table. I need the task names should be comma separated.
ModelName ObjectID ObjectName TaskName
Test Model 1 ABC TaskA, TaskB
Test Model 11 ABCD TaskX, TaskY
I tried the below query. But I don't know how to group Task names.
SELECT S1.ModelName,
S2.ID AS ObjectID,
S2.Name AS ObjectName,
S3.TaskName
FROM TableA
CROSS APPLY OPENJSON(JsonData)
WITH (Model NVARCHAR(MAX) '$.Model[0]' AS JSON) S1
CROSS APPLY OPENJSON (S1.Model)
WITH (Object NVARCHAR(MAX) '$.Object' AS JSON,
ID INT '$.ID',
Name NVARCHAR(250) '$.Name') S2
CROSS APPLY OPENJSON (S2.Object)
WITH (Task NVARCHAR(MAX) '$.Task' AS JSON ,
TaskName NVARCHAR(MAX) '$.TaskName') S3

You need to use STRING_AGG() to aggregate the text values and one possible approach (based on the attempt in the question) is the following statement. The aggregation of the task names is for each item in the Object JSON array:
Table:
CREATE TABLE TableA (JsonData varchar(max))
INSERT INTO TableA (JsonData) VALUES ('{
"Model": [
{
"ModelName": "Test Model",
"Object": [
{
"ID": 1,
"Name": "ABC",
"Task" : [
{
"TaskID" : 1222,
"Name": "TaskA"
},
{
"TaskID" : 154,
"Name": "TaskB"
}
]
},
{
"ID": 11,
"Name": "ABCD",
"Task" : [
{
"TaskID" : 222,
"Name": "TaskX"
},
{
"TaskID" : 234,
"Name": "TaskY"
}
]
}
]
}]}')
Statement:
SELECT
j1.ModelName,
j2.ObjectID, j2.ObjectName,
c.TaskName
FROM TableA t
CROSS APPLY OPENJSON(t.JsonData, '$.Model[0]') WITH (
ModelName varchar(50) '$.ModelName',
Object nvarchar(max) '$.Object' AS JSON
) j1
CROSS APPLY OPENJSON(j1.Object, '$') WITH (
ObjectID int '$.ID',
ObjectName varchar(50) '$.Name',
Task nvarchar(max) '$.Task' AS JSON
) j2
CROSS APPLY (
SELECT STRING_AGG([Name], ',') AS TaskName
FROM OPENJSON (j2.Task, '$') WITH (Name varchar(50) '$.Name')
) c

You need to use STRING_AGG() function, which applies to the DB version SQL Server 2017 and later, together with the below GROUP BY expression as
SELECT S1.ModelName, S2.ID AS ObjectID, S2.Name AS ObjectName,
STRING_AGG(S3.TaskName, ',') WITHIN GROUP (ORDER BY TaskName) AS TaskName
FROM <rest of your query>
GROUP BY S1.ModelName, S2.ID, S2.Name
as a complete query :
SELECT S1.ModelName, S3.ObjectID, S3.ObjectName,
STRING_AGG(S4.TaskName, ',') WITHIN GROUP (ORDER BY S4.TaskName) AS TaskName
FROM TableA
CROSS APPLY OPENJSON(JsonData)
WITH (ModelName NVARCHAR(255) '$.Model[0].ModelName') S1
CROSS APPLY OPENJSON (JsonData)
WITH (Object NVARCHAR(MAX) '$.Model[0].Object' AS JSON) S2
CROSS APPLY OPENJSON (S2.Object)
WITH (ObjectID INT '$.ID',
ObjectName NVARCHAR(255) '$.Name',
Task NVARCHAR(MAX) '$.Task' AS JSON) S3
CROSS APPLY OPENJSON (S3.Task)
WITH (TaskID NVARCHAR(MAX) '$.TaskID',
TaskName NVARCHAR(MAX) '$.Name') S4
GROUP BY S1.ModelName, S3.ObjectID, S3.ObjectName
Using WITHIN GROUP (ORDER BY TaskName) is optional, if you do not want ordering, then you can remove that part from the function as in the below demonstration :
Demo

Related

Select from json data is resulting in null values. How to select from this simple json data

I have the following JSON data:
declare #json nvarchar(max)=
'
[{
"images": [{
"key": "c:\\stapler\\booktest\\gray00024.jp2",
"imageNumber": 1
}],
"instrumentNumber": 94109416
},
{
"images": [{
"key": "c:\\stapler\\booktest\\gray00025.jp2",
"imageNumber": 1
},
{
"key": "c:\\stapler\\booktest\\gray00026.jp2",
"imageNumber": 2
}
],
"instrumentNumber": 94109417
},
{
"images": [{
"key": "c:\\stapler\\booktest\\gray00027.jp2",
"imageNumber": 1
},
{
"key": "c:\\stapler\\booktest\\gray00028.jp2",
"imageNumber": 2
}
],
"instrumentNumber": 94109418
}
]'
I am trying to pull the key and imageNumber from each of these records.
I have tried this query which will give me the instrument number, but gives NULL skey and imageNumber values:
select * from openjson (#json)
with(
instrumentNumber nvarchar(100) '$.instrumentNumber',
skey nvarchar(500) '$.images.key',
imageNumber nvarchar(500) '$.images.imageNumber')
Can anyone tell me what I am doing wrong?
Because you have a nested array (images) you need to extract those values in another openjson which you can then cross apply to the original:
select a.instrumentNumber, b.skey, b.imageNumber
from openjson (#json)
with (
instrumentNumber nvarchar(100) '$.instrumentNumber',
images nvarchar(max) as json
) a
cross apply openjson (a.images)
with (
skey nvarchar(500) '$.key',
imageNumber nvarchar(500) '$.imageNumber'
) b
Output for your sample data
instrumentNumber skey imageNumber
94109416 c:\stapler\booktest\gray00024.jp2 1
94109417 c:\stapler\booktest\gray00025.jp2 1
94109417 c:\stapler\booktest\gray00026.jp2 2
94109418 c:\stapler\booktest\gray00027.jp2 1
94109418 c:\stapler\booktest\gray00028.jp2 2
Demo on dbfiddle.uk

Update json data in oracle sql

This is my json data in one of the oracle sql columns "jsoncol" in a table named "jsontable"
{
"Company": [
{
"Info": {
"Address": "123"
},
"Name": "ABC",
"Id": 999
},
{
"Info": {
"Address": "456"
},
"Name": "XYZ",
"Id": 888
}
]
}
I am looking for an UPDATE query to update all the value of "Name" with a new value based on a particular "Id" value.
Thanks in advance
From Oracle 19, you can use JSON_MERGEPATCH:
UPDATE jsontable j
SET jsoncol = JSON_MERGEPATCH(
jsoncol,
(
SELECT JSON_OBJECT(
KEY 'Company'
VALUE JSON_ARRAYAGG(
CASE id
WHEN 999
THEN JSON_MERGEPATCH(
json,
'{"Name":"DEF"}'
)
ELSE json
END
FORMAT JSON
RETURNING CLOB
)
FORMAT JSON
RETURNING CLOB
)
FROM jsontable jt
CROSS APPLY JSON_TABLE(
jt.jsoncol,
'$.Company[*]'
COLUMNS(
json VARCHAR2(4000) FORMAT JSON PATH '$',
id NUMBER PATH '$.Id'
)
)
WHERE jt.ROWID = j.ROWID
)
)
Which, for the sample data:
CREATE TABLE jsontable (
jsoncol CLOB CHECK (jsoncol IS JSON)
);
INSERT INTO jsontable (jsoncol)
VALUES ('{
"Company": [
{
"Info": {
"Address": "123"
},
"Name": "ABC",
"Id": 999
},
{
"Info": {
"Address": "456"
},
"Name": "XYZ",
"Id": 888
}
]
}');
Then after the UPDATE, the table contains:
JSONCOL
{"Company":[{"Info":{"Address":"123"},"Name":"DEF","Id":999},{"Info":{"Address":"456"},"Name":"XYZ","Id":888}]}
db<>fiddle here
You can use REPLACE() within JSON_TABLE() function in order to update the value of the Name(from ABC to DEF) for a specific Id value(999) such as
UPDATE jsontable jt0
SET jsoncol = ( SELECT REPLACE(jsoncol,jt.name,'DEF')
FROM jsontable j,
JSON_TABLE(jsoncol,
'$' COLUMNS(NESTED PATH '$.Company[*]'
COLUMNS(
name VARCHAR2 PATH '$.Name',
id INT PATH '$.Id'
)
)
) jt
WHERE jt.id = 999
AND j.id = jt0.id )
for the DB version prior to 19 provided that the identity values(id) of the table and of the JSON values are unique throughout the table and each individual JSON value, respectively.
Demo

insert json to sql table getting null

I have the following json , when i am trying to extract it to sql i get empty.
I need CusP.id, CusP.custldId ,cusfield.id, value
DECLARE #json NVARCHAR(MAX);
SELECT #json = '{
"includ": {
"cusP": {
"542310": {
"id": 542310,
"custldId": 155,
"cusfield": {
"id": 155,
"type": "custfi"
},
"projectId": 17435,
"project": {
"id": 17435,
"type": "projects"
},
"value": "META DATA",
"createdAt": "2022-01-16T05:11:20Z",
"createdBy": 222222
},
"21000": {
"id": 21000,
"custldId": 426,
"cusfield": {
"id": 426,
"type": "custfi"
},
"projectId": 786044,
"project": {
"id": 786044,
"type": "projects"
},
"value": "delta55",
"createdAt": "2022-01-17T10:03:07Z",
"createdBy": 333333
}
}
}
}'
This is what i am trying:
SELECT
D.cusPid,
d.[value],
c.cusfieldid,
cd.projectId
FROM OPENJSON(#json, '$.includ.cusP')
WITH (
cusPid NVARCHAR(max) '$.id',
[value] NVARCHAR(max) '$.value'
) D
CROSS APPLY OPENJSON(#json, '$.includ.cusP.custfi')
WITH (
cusfieldid VARCHAR(100) '$.id'
) C
CROSS APPLY OPENJSON(#json, '$.includ.cusP.project')
WITH (
projectId VARCHAR(100) '$.id'
) Cd;
that is the result i expect
cusPid
value
cusfieldid
projectId
542310
META DATA
155
17435
21000
delta55
426
786044
The problem is that the ID is also itself used as the key for a sub-property and OPENJSON does not allow variable paths (beyond arrays), so you need an extra level:
SELECT P.id AS cuspID, P.[value], P.cusfieldid, [projectId]
FROM OPENJSON(#json, '$.includ.cusP') J
CROSS APPLY OPENJSON(J.[value]) WITH (
id INT,
[value] NVARCHAR(MAX),
[projectId] INT,
cusfieldid INT '$.cusfield.id'
) P

Data population from database as nested array object

I have a table structure as below in SQL Server database,
I want to populate the data from database something similar to JSON like as below:
id: 1
aname: xyz
categories: bus
{
arnam: res
street: [s1,s2]
},
{
arnam: com
street: [c1,c2]
}
Can someone please guide me as to how I can do this in the database using normal SQL query or procedure.
Your json is not valid, but according to your table I think you want to know how to parse data from nested JSON with array of values with this structure:
WITH cte AS (
SELECT * FROM (VALUES
('{"id": 1, "aname": "xyz",
"categories": {
"bus": [
{"aname": "res",
"street": ["c1", "c2"]
},
{"aname": "res",
"street": ["s1", "s2"]
}]
}
}'),
('{"id": 2, "aname": "abc",
"categories": {
"bus": [
{"aname": "foo",
"street": ["c1", "c2"]
},
{"aname": "zoo",
"street": ["s1", "s2"]
}]
}
}')
) t1 ([json])
)SELECT
ROW_NUMBER() OVER(ORDER BY [id]) AS RN,
*
FROM cte AS e
CROSS APPLY OPENJSON(e.[json]) WITH (
[id] int '$.id',
[aname] VARCHAR(100) '$.aname',
[categories_jsn] NVARCHAR(MAX) '$.categories.bus' AS JSON
) AS jsn
CROSS APPLY OPENJSON([categories_jsn]) WITH (
[street_arr] NVARCHAR(MAX) '$.street' AS JSON,
[aname_lvl2] VARCHAR(20) '$.aname'
) AS jsn2
CROSS APPLY OPENJSON([street_arr]) WITH (
[street] VARCHAR(20) '$'
)
Output:

I want to return a JSON in a variable of multiple tables In SQL 2017

I want to return a JSON in a variable of multiple tables In SQL 2017.
Create table TestingJson(ID int,FName varchar(20),LName varchar(20))
Insert into TestingJson(ID,FName,LName) Select 1,'Vishal','Mittal' union
Select 2,'Kunal','Singh'
Select * from TestingJson for json path,Root('Data')
Select count(*)[Count] from TestingJson for json path,Root('DataCount')
Declare #UserData varchar(max)
select #UserData = (Select * from TestingJson for json path,Root('Data')) + ',' + (Select count(*)[Count] from TestingJson for json path,Root('DataCount'))
select #UserData
Result:-
{"Data":[{"ID":1,"Name":"Vishal"},{"ID":2,"Name":"Kunal"}]},{"DataCount":[{"Count":2}]}
This is not returning a object of json or this is not a correct format of json but I want only one object of json like this-
{
"Data":[{
"ID":1,"FName":"Vishal","LName":"Mittal"},{
"ID":2,"FName":"Kunal","LName":"Singh"}],"DataCount":[{
"Count":2}]
}
Try this:
Select
(Select * from TestingJson for json path)[Data],
(Select count(*)[Count] from TestingJson for json path)[DataCount]
for json path, without_array_wrapper
It produces the required output
{
"Data": [
{
"ID": 1,
"FName": "Vishal",
"LName": "Mittal"
},
{
"ID": 2,
"FName": "Kunal",
"LName": "Singh"
}
],
"DataCount": [
{
"Count": 2
}
]
}