Combining two tables result into JSON - SQL server - sql

I am having two tables STUDENT and MASTER as follows
CREATE TABLE student(sid int,sname varchar(10),saddress varchar(30))
CREATE TABLE master(mid int,mname varchar(10),maddress varchar(30))
Now I want the JSON Structure as
{
"student": [
{
"sid": "value",
"sname": "value",
"saddress": "value"
}
],
"master": [
{
"mid": "value",
"mname": "value",
"maddress": "value"
}
]
}
In short I can say:
{
"table1":[],
"table2":[]
}
I have tried this but result is not as expected
SELECT * FROM student,master FOR JSON AUTO
Can any one help me to form the required JSON Structure from the query ??

Couple ideas:
SELECT student,
[master] --This is a poor choice for an object, as master is the name of a system database
FROM (VALUES((SELECT * FROM dbo.student FOR JSON AUTO),
(SELECT * FROM dbo.[master] FOR JSON AUTO)))V(student,[master])
FOR JSON AUTO;
SELECT (SELECT *
FROM dbo.student
FOR JSON AUTO) AS student,
(SELECT *
FROM dbo.[master] --This is a poor choice for an object, as master is the name of a system database
FOR JSON AUTO) AS [master]
FOR JSON PATH;

Related

Convert nested JSON to SQL table in SQL Server

I am trying to convert a JSON file into a SQL table in SQL Server and running across an error that I cannot seem to find a solution for to save my life.
In addition to the error resolution, I would also like to go a step further and breakdown the employee ID values to not be in a single cell but rather split into separate rows.
Below is the code I am using which includes a sample JSON structure:
drop table if exists newtable1;
declare #json NVARCHAR(MAX)
--select #json=BulkColumn
--from openrowset (bulk 'C:\Users\hamza\Documents\Price Transparency\banking_sample.json',single_clob) as j;
= N'{
"comapny_name": "chase",
"company_type": "banking",
"last_updated_on": "2020-08-27",
"institutional":[{
"region_id": 1,
"groups": [{
"employee_id": [1111111111, 2222222222, 3333333333, 4444444444, 5555555555],
"site":{
"type": "atm",
"id": "11-1111111"
}
},{
"employee_id": [1111111111, 2222222222, 3333333333, 4444444444, 5555555555],
"site":{
"type": "branch",
"id": "22-2222222"
}
}]
},{
"region_id": 2,
"location": "new york city, ny"
}]
}';
select
JSON_VALUE(a.value,'$.company_name') as company_name,
JSON_VALUE(a.value,'$.company_type') as reporting_entity_type,
JSON_VALUE(a.value,'$.last_updated_on') as plan_name,
JSON_VALUE(b.value,'$.region_id') as prov_grp_id,
JSON_VALUE(b.value,'$.location') as loc,
JSON_VALUE(c.value,'$.employee_id') as npi,
JSON_VALUE(c.value,'$.site.type') as tin_type,
JSON_VALUE(c.value,'$.site.id') as tin_value
into newtable1
from openjson (#json) as a
cross apply openjson(a.value,'$.institutional') as b
cross apply openjson(b.value,'$.groups') as c;

GET last element of array in json column of my Transact SQL table

Thanks for helping.
I have my table CONVERSATIONS structured in columns like this :
[ ID , JSON_CONTENT ]
In the column ID i have a simple id in Varchar
In the column JSON_CONTENT i something like this :
{
"id_conversation" : "25bc8cbffa8b4223a2ed527e30d927bf",
"exchanges": [
{
"A" : "...",
"B": "..."
},
{
"A" : "...",
"B": "..."
},
{
"A" : "...",
"Z" : "..."
}
]
}
I would like to query and get the id and the last element of exchanges :
[ ID , LAST_ELT_IN_EXCHANGE_IN_JSON_CONTENT]
I wanted to do this :
select TOP 3 ID, JSON_QUERY(JSON_CONTENT, '$.exchange[-1]')
from CONVERSATION
But of course Transact SQL is not Python.
I saw theses answers, but i don't know how to applicate to my problem.
Select last value from Json array
Thanks for helping <3
If I understand you correctly, you need an additional APPLY operator and a combination of OPENJSON() and ROW_NUMBER(). The result from the OPENJSON() call is a table with columns key, value and type and when the JSON content is an array, the key column returns the index of the element in the specified array:
Table:
SELECT ID, JSON_CONTENT
INTO CONVERSATION
FROM (VALUES
(1, '{"id_conversation":"25bc8cbffa8b4223a2ed527e30d927bf","exchanges":[{"A":"...","B":"..."},{"A":"...","B":"..."},{"A":"...","Z":"..."}]}')
) v (ID, JSON_CONTENT)
Statement:
SELECT c.ID, j.[value]
FROM CONVERSATION c
OUTER APPLY (
SELECT [value], ROW_NUMBER() OVER (ORDER BY CONVERT(int, [key]) DESC) AS rn
FROM OPENJSON(c.JSON_CONTENT, '$.exchanges')
) j
WHERE j.rn = 1
Result:
ID value
------------------------
1 {
"A" : "...",
"Z" : "..."
}
Notice, that -1 is not a valid array index in your path expression, but you can access the item in a JSON array by index (e.g. '$.exchanges[2]').

JSON_MODIFY all values without looping

See sample below. How would I use JSON_MODIFY or other way to modify all the "disc" values to "100" without having to update each array item in a loop?
create table #temp_data (json_text nvarchar(max))
insert into #temp_data select
'
"curr":"USD",
"items":[
{
"line":1,
"disc":10,
},
{
"line":2,
"disc":11
},
{
"line":3,
"disc":12,
}
]
}'
select * from #temp_data
We don't actually need to parse the rest of the JSON, we only need the $.items part. So we can APPLY that property with OPENJSON, then reassemble it with JSON_MODIFY:
UPDATE t
SET json_text = JSON_MODIFY(t.json_text, '$.items', v.items)
FROM temp_data t
CROSS APPLY (
SELECT line, disc = 100
FROM OPENJSON(t.json_text, '$.items') WITH (line int) AS items
FOR JSON PATH
) v(items);
In the WITH block, we need to add all properties we are not modifying, then in the inner SELECT we add any columns we want to change.
One way would be to use the traditional SQL DML UPDATE to replace the json_text with a new piece of JSON derived from the existing. Something like this
JSON_MODIFY could be added if that's a requirement.
drop table if exists #temp_data;
go
create table #temp_data (json_text nvarchar(max));
insert into #temp_data(json_text) values(
N'{
"curr":"USD",
"items":[
{
"line":1,
"disc":10
},
{
"line":2,
"disc":11
},
{
"line":3,
"disc":12
}
]
}');
update #temp_data
set json_text=( select json_value(d.json_text, N'strict $.curr') curr,
(select j2.line, j2.disc+100 as disc
from #temp_data td
cross apply openjson(td.json_text)
with(curr nvarchar(20),
items nvarchar(max) as json) j1
cross apply openjson(j1.items)
with(line int,
disc int) j2
for json path) items
from #temp_data d
for json path, without_array_wrapper);
select * from #temp_data;
{
"curr": "USD",
"items": [
{
"line": 1,
"disc": 210
},
{
"line": 2,
"disc": 211
},
{
"line": 3,
"disc": 212
}
]
}
It's not possible to use a wildcard in a JSON_MODIFY() call, so one possible approach are the following steps:
Parse the $.items array from the stored JSON using OPENJSON() and explicit schema including the line key.
Set the new value for the disc key for each item of this array.
Generate the JSON again using FOR JSON PATH.
Update the table with JSON_MODIFY().
Table:
create table #temp_data (json_text nvarchar(max))
insert into #temp_data (json_text)
VALUES (N'
{
"curr":"USD",
"items":[
{"line":1, "disc":10},
{"line":2, "disc":11},
{"line":3, "disc":12}
]
}')
Statement:
UPDATE #temp_data
SET json_text = JSON_MODIFY(
json_text,
'$.items',
(
SELECT line, 100 AS disc
FROM OPENJSON(json_text, '$.items') WITH (line int '$.line')
FOR JSON PATH
)
)
Result:
json_text
{
"curr":"USD",
"items":[{"line":1,"disc":100},{"line":2,"disc":100},{"line":3,"disc":100}]
}

MSSQL Query JSON displays Null value

I have a table PublicRelations with a column called Students in a SQL Server database called Subjects.
[
{ "Label": "Name", "ColumnValue": "Trudie" },
{ "Label": "Class", "ColumnValue": "PublicRelations" },
{ "Label": "Room", "ColumnValue": "8049" },
{ "Label": "HttpPath", "ColumnValue": "https://www.google.com/" }
]
I only get NULL when I run the below query using the Json_value. I'd like to get it to display the value from the array. I believe this may have to do with the 4000 character limit?
SELECT [StuduentID],
[Students],
--JSON_VALUE([Students],'$.ColumnValue') AS Name --Only returns NULL
FROM [Subjects].[dbo].[PublicRelations] c
CROSS APPLY OPENJSON(c.Students)
WITH ( Name int '$.Name',
Value nvarchar(255) '$.ColmunValue'
) AS jsonValues
WHERE jsonValues.ColumnValue = 'Trudie'
The query works and I can find what I need, but again, I only get NULL when I want to display that part of the JSON column in my results.
The statement is wrong and you has the following issues (as #MartinSmith already mentioned):
Syntax error - '$.ColmunValue' should be '$.ColumnValue'.
Wrong schema definition (the WITH clause) - I can't see Name key in the input JSON.
Wrong use of JSON_VALUE() - this function extracts scalar value from a JSON string, so JSON_VALUE([Students],'$.ColumnValue') returns NULL with this JSON input in lax mode.
You may try with the following statement (based on the statement in the question):
Table:
CREATE TABLE PublicRelations (
StudentID int,
Students nvarchar(1000))
INSERT INTO PublicRelations (StudentID, Students)
VALUES (1, N'[
{ "Label": "Name", "ColumnValue": "Trudie" },
{ "Label": "Class", "ColumnValue": "PublicRelations" },
{ "Label": "Room", "ColumnValue": "8049" },
{ "Label": "HttpPath", "ColumnValue": "https://www.google.com/" }
]')
Statement:
SELECT p.StudentID, j.*
FROM [PublicRelations] p
CROSS APPLY OPENJSON(p.Students) WITH (
Name nvarchar(50) '$.Label',
Value nvarchar(255) '$.ColumnValue'
) j
WHERE EXISTS (
SELECT 1
FROM OPENJSON(p.Students) WITH (Value nvarchar(255) '$.ColumnValue')
WHERE Value = N'Trudie'
) AND (j.Name IN ('Name', 'Class', 'Room'))
Result:
StudentID Name Value
1 Name Trudie
1 Class PublicRelations
1 Room 8049

How to write a select query to get the index value from Json object

I have the below JSON object. I need to write a select query to get the index values of Object JSON array. Kind of getting the sequence value.
{
"Model": [
{
"ModelName": "Test Model",
"Object": [
{
"ID": 1,
"Name": "ABC",
},
{
"ID": 11,
"Name": "ABCD",
},
{
"ID": 15,
"Name": "ABCDE",
},
]
}]}
Expected Output:
Index_Value
1
2
3
If I understand the question correctly and you want to get the index of the items in the Object JSON array, you need to use OPENJSON() with default schema. The result is a table with columns key, value and type and in case of JSON array, the key column holds the index of each item in the array (0-based):
JSON:
DECLARE #json nvarchar(max) = N'{
"Model":[
{
"ModelName":"Test Model",
"Object":[
{
"ID":1,
"Name":"ABC"
},
{
"ID":11,
"Name":"ABCD"
},
{
"ID":15,
"Name":"ABCDE"
}
]
}
]
}'
Statement:
SELECT CONVERT(int, j2.[key]) + 1 AS item_id
FROM OPENJSON (#json, '$.Model') j1
CROSS APPLY OPENJSON(j1.[value], '$.Object') j2
But if you want to get the values of the ID keys in the Object JSON array, the statement is different:
SELECT j2.ID
FROM OPENJSON (#json, '$.Model') j1
CROSS APPLY OPENJSON(j1.[value], '$.Object') WITH (
ID int '$.ID'
) j2
Note, that you need two OPENJSON() calls, because the input JSON has nested array structure. Of course, if Model JSON array has always one item, you may simplify the statement using an appropriate path:
SELECT CONVERT(int, [key]) + 1 AS item_id
FROM OPENJSON (#json, '$.Model[0].Object')
Finally, to get index, ID and Name, you should use the following statement, which assumes, that $.Model JSON array has more than one item and defines ID and Name columns with the appropraite data types:
SELECT
CONVERT(int, j2.[key]) + 1 AS ItemID,
j3.ID, j3.Name
FROM OPENJSON (#json, '$.Model') j1
CROSS APPLY OPENJSON(j1.[value], '$.Object') j2
CROSS APPLY OPENJSON(j2.[value], '$') WITH (
ID int '$.ID',
Name varchar(50) '$.Name'
) j3
DECLARE #json nvarchar(max) = N'{
"Model":[
{
"ModelName":"Test Model",
"Object":[
{
"ID":1,
"Name":"ABC"
},
{
"ID":11,
"Name":"ABCD"
},
{
"ID":15,
"Name":"ABCDE"
}
]
}
]
}'
declare #i int=0;
SELECT
j2.ID, j2.Name
FROM OPENJSON (#json, '$.Model') j1
CROSS APPLY OPENJSON(j1.[value],concat('$.Object[',#i,']')) WITH (
ID i`enter code here`nt '$.ID', Name varchar(100) '$.Name'
) j2
Results:-
ID
Name
11
ABCD
you can select the key columns in select clause no need to mention in with of crossjoin.
SELECT
distinct t.id,
JSON_VALUE(AttsData.[value], '$.address') as address,
JSON_VALUE(AttsData.[value], '$.name') as name,
JSON_VALUE(AttsData.[value], '$.owner_name') as owner_name,
JSON_VALUE(AttsData.[value], '$.project') as project
,CONVERT(int, AttsData.[key]) index_id
FROM mytablewithjsonfeild t
CROSS APPLY OPENJSON (t."jsonfeild",N'$.parentkey') as AttsData
Above query, from the table I have cross joined the JSON field. and in select statement i have taken the specific keys.
and CONVERT(int, AttsData.[key]) to get the index of the elements