How do I get data from JSON Array MSSQL - sql

If I do this I can get the first value in the array. But how can I get all of the values in the list ?
SELECT
JSON_VALUE('{"Distributor": [5030, 4000, 1231]}', '$.Distributor[0]') AS result;

SELECT value
FROM OPENJSON('{"Distributor": [5030, 4000, 1231]}','$.Distributor')
'$.Distributor' is the 'start path' to start looking for an array

You can take look at this article:
https://learn.microsoft.com/fr-fr/sql/relational-databases/json/json-data-sql-server?view=sql-server-2017
Using function Openjson and Outer apply
Example provided:
DECLARE #json NVARCHAR(MAX)
SET #json =
N'[
{ "id" : 2,"info": { "name": "John", "surname": "Smith" }, "age": 25 },
{ "id" : 5,"info": { "name": "Jane", "surname": "Smith", "skills": ["SQL", "C#", "Azure"] }, "dob": "2005-11-04T12:00:00" }
]'
SELECT *
FROM OPENJSON(#json)
WITH (id int 'strict $.id',
firstName nvarchar(50) '$.info.name', lastName nvarchar(50) '$.info.surname',
age int, dateOfBirth datetime2 '$.dob',
skills nvarchar(max) '$.info.skills' as json)
outer apply openjson( skills )
with ( skill nvarchar(8) '$' )
EDIT Code with provided json :
DECLARE #json NVARCHAR(MAX)
SET #json = N'{"Distributor": [5030, 4000, 1231]}'
SELECT Distributor
FROM OPENJSON(#json)
WITH (Distributors nvarchar(max) '$.Distributor' as json)
outer apply openjson( Distributors )
with ( Distributor int '$' )
RESULT :
Distributor
5030
4000
1231

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

Transform properties from JSON array into comma-separated string

I have a string column in an SQL-Server table on Azure which contains the following data:
{
"status": "success",
"data": [
{
"name": "Jane",
"type": 0
},
{
"name": "John",
"type": 0
}
]
}
How can it be transformed into a comma-separated string containing "Jane, John"?
Here how to achieve this via a snippet of some of my older code, you should be able to loop through the table and do this for each row. There may be a quicker way of doing it but this will work.
DECLARE #JSON NVARCHAR(200) = '{"status": "success", "data": [{"name": "Jane", "type": 0},{"name": "John", "type": 0}]}',
#result nvarchar(max) = ''
SELECT #result = #result + [value] + N', '
FROM (
SELECT DISTINCT data.value
FROM OPENJSON(#JSON, '$.data') as jsondata
CROSS APPLY OPENJSON(jsondata.value) as data
WHERE data.[key] = 'name') a
select #result = substring(#result, 1, (LEN(#result)-1))
select #result

Map JSON KEY as column names in INSERT QUERY

I am writing a stored procedure to insert these values into a table. Always my table column name will be the key and column data will be the value in the JSON.
DECLARE #json NVARCHAR(MAX) = N'[
{
"name": "abcd",
"id": 12,
"feelings": {
"happy": 0,
"angry": 1,
"sad": 1
}
},
{
"name": "abcdf",
"id": 14,
"feelings": {
"happy": 0,
"angry": 1,
"sad": 1
}
}
]'
DECLARE #id INT;
DECLARE #last_name NVARCHAR(50);
SET #id =10;
SET #last_name = 'Mike'
Example:
INSERT INTO Table([name],[id],[lastname],[happy],[angry],[sad])
VALUES ("abcd",#id,#last_name,0,1,1)
How can I achieve this for any JSON format? Always the JSON key should be mapped to the column name. The insert statement should be able to insert all the entries from the JSON. Only the key inside the feelings will change. All others remain the same.
I need to include data from the JSON as well as static declared data in the insert query.Does OPENJSON allow including static data in WITH().
Please help me with this.
I think that dynamic statement should be your first option:
JSON:
DECLARE #json nvarchar(max) = N'[
{
"name": "abcd",
"id": 12,
"feelings": {
"happy": 0,
"angry": 1,
"sad": 1
}
},
{
"name": "abcdf",
"id": 14,
"feelings": {
"happy": 0,
"angry": 1,
"sad": 1
}
}
]'
Statement:
DECLARE #stm nvarchar(max)
DECLARE #columns nvarchar(max)
DECLARE #schema nvarchar(max)
DECLARE #id int
SET #id = 10
SELECT
#columns = STRING_AGG(QUOTENAME([key]), N','),
#schema = STRING_AGG(CONCAT(QUOTENAME([key]), N' int ''$.feelings."', [key], '"'''), N',')
FROM OPENJSON(#json, '$[0].feelings')
SELECT #stm = CONCAT(
N'INSERT INTO InputTable ([id],[name],',
#columns,
N') SELECT #id,[name],',
#columns,
N' FROM OPENJSON(#json) WITH ([name] varchar(100) ''$."name"'',',
#schema,
N')'
)
PRINT #stm
EXEC sp_executesql #stm, N'#json nvarchar(max), #id int', #json, #id
Generated dynamic statement:
INSERT INTO InputTable ([id],[name],[happy],[angry],[sad])
SELECT #id,[name],[happy],[angry],[sad]
FROM OPENJSON(#json) WITH (
[name] varchar(100) '$."name"',
[happy] int '$.feelings."happy"',
[angry] int '$.feelings."angry"',
[sad] int '$.feelings."sad"'
)
I think you're looking for something like this. This opens and flattens the JSON
declare
#json nvarchar(max)=N'[
{
"name": "abcd",
"id": 12,
"feelings": {
"happy": 0,
"angry": 1,
"sad": 1
}
},
{
"name": "abcdf",
"id": 14,
"feelings": {
"happy": 0,
"angry": 1,
"sad": 1
}
}
]';
INSERT INTO Table([name],[happy],[angry],[sad])
select oj.[name], f.*
from openjson(#json) with (name nvarchar(4000),
id int,
feelings nvarchar(max) as json) oj
cross apply
openjson(oj.feelings) with (happy int,
angry int,
sad int) f;
Results
name id happy angry sad
abcd 12 0 1 1
abcdf 14 0 1 1
Not sure I got your question correctly, but if you need to get data from JSON based on columns existing in table which you want to pass by name then you need to have dynamic sql. So here's an example of how you can do it using sys.columns view:
drop table if exists dbo.temp_data
create table dbo.temp_data (name nvarchar(128), happy bit, angry bit, sad bit);
----------------------------------------------------------------------------------------------------
declare #table_name nvarchar(256) = 'dbo.temp_data'
declare #data nvarchar(max) = '[
{
"name": "abcd",
"id": 12,
"feelings": {
"happy": 0,
"angry": 1,
"sad": 1
}
},
{
"name": "abcdf",
"id": 14,
"feelings": {
"happy": 0,
"angry": 1,
"sad": 1
}
}
]';
declare #stmt nvarchar(max);
declare #stmt_part1 nvarchar(max);
declare #stmt_part2 nvarchar(max);
select
#stmt_part1 = concat(isnull(#stmt_part1 + ',', ''),c.name),
#stmt_part2 = concat(isnull(#stmt_part2 + ',', ''),'json_value(o.value, ''$.feelings.',c.name,''')')
from sys.columns as c
where
c.object_id = object_id(#table_name) and
c.name <> 'name'
set #stmt = concat('
insert into ',#table_name,' (name,',#stmt_part1,')
select
json_value(o.value, ''$.name'') as name,',#stmt_part2,'
from openjson(#data) as o
');
exec sys.sp_executesql
#stmt,
N'#data nvarchar(max)',
#data = #data;
----------------------------------------------------------------------------------------------------
select * from dbo.temp_data
I don't know which version of Sql Server you're using so I'm not sure if you can use string_agg system function so I've used pretty standard trick to aggregate column names into string.

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

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

Inserting into sql server tables (2016) from json

I have some json like this:
SET #json =N'[
{ "id" : 2,"name": "John", "surname": "Smith", "lastname":"", "age": 25 },
]'
I need to insert into table with a condition like IF LASTNAME IS EMPTY IN JSON THEN INSERT SURNAME INTO LASTNAME ELSE INSERT LASTNAME INTO LASTNAME
insert into mytable (id,firstname,lastname,age)
select id,name,case statement,age from openjson
WITH (id int 'strict $.id',name nvarchar(100) '$.name',case statement, age int '$.age');
Hi i think this query can respond :
DECLARE #json varchar(MAX)
SET #json =N'[
{ "id" : 2,"name": "John", "surname": "Smith", "lastname":"", "age": 25 },
{ "id" : 2,"name": "John", "surname": "Smith", "lastname":"TT", "age": 25 },
{ "id" : 2,"name": "John", "surname": "Smith", "lastname":"TEST", "age": 25 }
]'
select id,name,case when lastname = '' then surname else lastname end as lastnameup, age from openjson(#json)
WITH (id int 'strict $.id',name nvarchar(100) '$.name', surname nvarchar(100) '$.surname', lastname nvarchar(100) '$.lastname', age int '$.age');
EDIT for surname propose thanks to #Shnugo