Extract data from Json string and divide into multiple columns - json

I have a column in a table that has Jsonstring text:
[
{
"PType":{"code":"9","name":"Hospitality"},
"PSubType":{"code":"901","name":"Hotel"},
"AType":{"code":"9","name":"Hospitality"},
"ASubType":{"code":"901","name":"Hotel"}
}
]
How can I divide that into multiple columns using sql server query?

With SQL-Server 2016+ there is native JSON support:
DECLARE #json NVARCHAR(MAX)=
N'[
{
"PType":{"code":"9","name":"Hospitality"},
"PSubType":{"code":"901","name":"Hotel"},
"AType":{"code":"9","name":"Hospitality"},
"ASubType":{"code":"901","name":"Hotel"}
}
]';
SELECT A.[key]
,JSON_VALUE(A.value,'$.code') AS Code
,JSON_VALUE(A.value,'$.name') AS [Name]
FROM OPENJSON(JSON_QUERY(#json,'$[0]')) A;
The result
key Code Name
---------------------------------
PType 9 Hospitality
PSubType 901 Hotel
AType 9 Hospitality
ASubType 901 Hotel
Some explanation:
With JSON_QUERY() you can get the element within the array, OPENJSON will find all objects within and return them as derived table.
JSON_VALUE will read the internals into columns.
Hint
with a version below v2016 you should use another tool or think about a CLR function...

In SQL Server 2016+ you can use a combination of openjson (more info here) and cross apply:
declare #json nvarchar(max) = '[ { "PType":{"code":"9","name":"Hospitality"}, "PSubType":{"code":"901","name":"Hotel"}, "AType":{"code":"9","name":"Hospitality"}, "ASubType":{"code":"901","name":"Hotel"} } ]'
select
[PT].[code] as Ptype_Code
,[PT].[name] as Ptype_Name
,[PS].[code] as PSubType_Code
,[PS].[name] as PSubType_Name
,[AT].[code] as AType_Code
,[AT].[name] as AType_Name
,[AS].[code] as ASubType_Code
,[AS].[name] as ASubType_Name
from openjson (#json)
with
(
PType nvarchar(max) as json,
PSubType nvarchar(max) as json,
AType nvarchar(max) as json,
ASubType nvarchar(max) as json
) as lev1
cross apply openjson (lev1.PType)
with
(
code int,
name nvarchar(100)
) as PT
cross apply openjson (lev1.PSubType)
with
(
code int,
name nvarchar(100)
) as PS
cross apply openjson (lev1.AType)
with
(
code int,
name nvarchar(100)
) as [AT]
cross apply openjson (lev1.ASubType)
with
(
code int,
name nvarchar(100)
) as [AS]
Result:

Related

Reading mulitple json array into rows in SQL Server

Given the sample json data below, how can I write a query to pull the array data all in one step to individual column?
DECLARE #json NVARCHAR(MAX);
SET #json = N'{
"Title":"ReportExport",
"Attachment":"",
"Name":"Dhoni",
"FirstTextArea":"Dhoni",
"Radio":"First",
"CheckBox":"{C++~.Net}",
"FileUpload":"",
"FirstGroupitem":[
{
"Address":"QTUvNU55THBxT2hmVXFkWGpia2NJQT09",
"Age":"30",
"TestField":"",
"Country":"ind",
"SecondTextArea":"11"
},
{
"Address":"OVpuaXpxNTlrZWg4dGI4VXRYMUg0Zz09",
"Age":"30",
"TestField":"",
"Country":"us",
"SecondTextArea":"22"
},
{
"Address":"WGErNFU2S0tYekdsRWZTT2NxSzZLQT09",
"Age":"30",
"TestField":"",
"Country":"us",
"SecondTextArea":"33"
}
],
"SecondGroupitem":[
{
"Address1":"QTUvNU55THBxT2hmVXFkWGpia2NJQT09",
"Age1":"30"
},
{
"Address1":"OVpuaXpxNTlrZWg4dGI4VXRYMUg0Zz09",
"Age1":"30"
}
]
}';
Statement:
SELECT i.Title,i.Attachment,i.Name,i.FirstTextArea,i.Radio,i.CheckBox,i.FileUpload,'FirstGroupitem' as FirstGroupitem,
a.Address, a.Age,a.TestField,a.Country,a.SecondTextArea
FROM OPENJSON(#json)
WITH (
Title VARCHAR(max) N'$.Title',
Attachment VARCHAR(max) N'$.Attachment',
Name VARCHAR(max) N'$.Name',
FirstTextArea VARCHAR(max) N'$.FirstTextArea',
Radio VARCHAR(max) N'$.Radio',
CheckBox VARCHAR(max) N'$.CheckBox',
FileUpload VARCHAR(max) N'$.FileUpload',
FirstGroupitem nvarchar(max) '$.FirstGroupitem' AS JSON
) AS i
CROSS APPLY (
SELECT *
FROM OPENJSON(i.FirstGroupitem)
WITH (
Address VARCHAR(max) N'$.Address',
Age VARCHAR(max) N'$.Age',
TestField VARCHAR(max) N'$.TestField',
Country VARCHAR(max) N'$.Country',
SecondTextArea VARCHAR(max) N'$.SecondTextArea'
)
) a
I want output like this:
You need to join the items from the $.FirstGroupitem" and $."SecondGroupitem JSON arrays by index:
Statement:
SELECT
i.Title, i.Attachment, i.Name, i.FirstTextArea, i.Radio, i.CheckBox,
j.FirstGroupAddress, j.SecondGroupAddress
FROM OPENJSON(#json)
WITH (
Title VARCHAR(max) N'$.Title',
Attachment VARCHAR(max) N'$.Attachment',
Name VARCHAR(max) N'$.Name',
FirstTextArea VARCHAR(max) N'$.FirstTextArea',
Radio VARCHAR(max) N'$.Radio',
CheckBox VARCHAR(max) N'$.CheckBox',
FileUpload VARCHAR(max) N'$.FileUpload',
FirstGroupitem nvarchar(max) '$.FirstGroupitem' AS JSON,
SecondGroupitem nvarchar(max) '$.SecondGroupitem' AS JSON
) AS i
OUTER APPLY (
SELECT f2.Address AS FirstGroupAddress, s2.Address AS SecondGroupAddress
FROM OPENJSON (i.FirstGroupitem) f1
FULL JOIN OPENJSON (i.SecondGroupitem) s1 ON f1.[key] = s1.[key]
OUTER APPLY OPENJSON(f1.[value]) WITH (
Address varchar(100) '$.Address'
-- Additional columns here
) f2
OUTER APPLY OPENJSON(s1.[value]) WITH (
Address varchar(100) '$.Address1'
-- Additional columns here
) s2
) j
Result:
Title Attachment Name FirstTextArea Radio CheckBox FirstGroupAddress SecondGroupAddress
---------------------------------------------------------------------------------------------------------------------------------
ReportExport Dhoni Dhoni First {C++~.Net} QTUvNU55THBxT2hmVXFkWGpia2NJQT09 QTUvNU55THBxT2hmVXFkWGpia2NJQT09
ReportExport Dhoni Dhoni First {C++~.Net} OVpuaXpxNTlrZWg4dGI4VXRYMUg0Zz09 OVpuaXpxNTlrZWg4dGI4VXRYMUg0Zz09
ReportExport Dhoni Dhoni First {C++~.Net} WGErNFU2S0tYekdsRWZTT2NxSzZLQT09

Parse JSON in Microsoft SQL

I have the following JSON,
And I have no clue as to how to parse "Value" (When you run it in SQL you get 3 columns key, value and type)
Any ideas?
DECLARE #json NVARCHAR(MAX);
SET #json = N'[
{"salesDate":"2020-03-02","storeSales":[
{"storeId":"104","sales":[
{"productId":"20002","salesVolume":0.700,"salesQuantity":2,"lastChanged":{"date":"2020-03-03","time":"07:28:06"}},
{"productId":"74301","salesVolume":0.750,"salesQuantity":1,"lastChanged":{"date":"2020-03-03","time":"07:28:06"}},
{"productId":"642401","salesVolume":0.750,"salesQuantity":1,"lastChanged":{"date":"2020-03-03","time":"07:28:06"}},
{"productId":"784001","salesVolume":2.100,"salesQuantity":3,"lastChanged":{"date":"2020-03-03","time":"07:28:06"}},
{"productId":"1013801","salesVolume":1.500,"salesQuantity":2,"lastChanged":{"date":"2020-03-03","time":"07:28:06"}},
{"productId":"1202801","salesVolume":0.750,"salesQuantity":1,"lastChanged":{"date":"2020-03-03","time":"07:28:06"}},
{"productId":"1209901","salesVolume":0.700,"salesQuantity":1,"lastChanged":{"date":"2020-03-03","time":"07:28:06"}},
{"productId":"1282201","salesVolume":0.750,"salesQuantity":1,"lastChanged":{"date":"2020-03-03","time":"07:28:06"}},
{"productId":"3317301","salesVolume":1.500,"salesQuantity":2,"lastChanged":{"date":"2020-03-03","time":"07:28:06"}},
{"productId":"4801301","salesVolume":0.700,"salesQuantity":1,"lastChanged":{"date":"2020-03-03","time":"07:28:06"}},
{"productId":"5780106","salesVolume":6.000,"salesQuantity":2,"lastChanged":{"date":"2020-03-03","time":"07:28:06"}},
{"productId":"7964902","salesVolume":0.375,"salesQuantity":1,"lastChanged":{"date":"2020-03-03","time":"07:28:06"}},
{"productId":"10785001","salesVolume":0.750,"salesQuantity":1,"lastChanged":{"date":"2020-03-03","time":"07:28:06"}},
{"productId":"11037501","salesVolume":1.500,"salesQuantity":2,"lastChanged":{"date":"2020-03-03","time":"07:28:06"}}]}]}]';
SELECT *
FROM OPENJSON(#json)
Assuming you wanted to get the sales data try this (although I am not 100% sure if this query offers the best performance)
SELECT [SalesDate], [StoreId], [ProductId], [SalesVolume], [SalesQuantity]
FROM OPENJSON(#json) WITH (
[SalesDate] DATETIME '$.salesDate',
[StoreSales] NVARCHAR(MAX) '$.storeSales' AS JSON
)
OUTER APPLY OPENJSON(StoreSales) WITH (
[StoreId] INT '$.storeId',
[Sales] NVARCHAR(MAX) '$.sales' AS JSON
)
OUTER APPLY OPENJSON(Sales) WITH (
[ProductId] INT '$.productId',
[SalesVolume] DECIMAL(18, 4) '$.salesVolume',
[SalesQuantity] INT '$.salesQuantity'
)
Value is the first object in your JSON array, which is itself another JSON object. SO you will have to read it using other SQL Server JSON utilities. For example:
SELECT JSON_VALUE(Value, '$.salesDate')
FROM OPENJSON(#json)

parsing json values in sql server

I want to parse the below json values.
DECLARE #json NVARCHAR(MAX)
SET #json =
N'[{"ID":1,"Roles":[1,2]},{"ID":2"Roles":[1,2,3]},{"ID":3,"Roles":[1,2,3,4]}]'
i want to display below output
Required Output
ID ROLES
1 1
1 2
2 1
2 2
2 3
3 1
3 2
3 3
3 4
I want query for this.
An OPENJSON with a WITH unrolls the outer layer, then a regular one can be used to unroll the arrays. (The alias isn't strictly necessary, I just think it's clearer, and it becomes necessary if you have to peel even more layers.)
SELECT ID, R.[Value] AS [Role]
FROM OPENJSON(#json) WITH (
ID INT,
[Roles] NVARCHAR(MAX) AS JSON
)
CROSS APPLY OPENJSON([Roles]) R
Try this:
DECLARE #json NVARCHAR(MAX)
SET #json =
N'[{"ID":1,"Roles":[1,2]},{"ID":2, "Roles":[1,2,3]},{"ID":3,"Roles":[1,2,3,4]}]'
SELECT pvt.[ID]
,roles.value
FROM
(
SELECT js.[key] as [key_id]
,roles.[key]
,roles.value
FROM OPENJSON(#json) js
CROSS APPLY OPENJSON(js.value) roles
) DS
PIVOT
(
MAX([value]) FOR [key] IN ([ID], [Roles])
) PVT
CROSS APPLY OPENJSON(pvt.roles) roles
or just this:
SELECT JSON_VALUE(js.value, '$.ID')
,ds.[value]
FROM OPENJSON(#json) js
CROSS APPLY OPENJSON(JSON_QUERY(js.value, '$.Roles')) ds;

Check for unique JSON keys in SQL Server

In SQL Server, how can I check if a string is valid JSON and the keys are all unique?
According to the T-SQL documentation, the regular ISJSON method does not check that the keys on the same level are unique.
You can use a Recursive Common Table Expression to do this. EG something like:
DECLARE #json NVARCHAR(4000) = N'{
"StringValue":"John",
"IntValue":45,
"TrueValue":true,
"FalseValue":false,
"NullValue":null,
"ArrayValue":["a","r","r","a","y"],
"ObjectValue":{"obj":"ect"}
}';
with q as
(
select [key] path, [key], value, type, 0 level
from openjson(#json)
union all
select concat(q.path,'\',n.[key]), n.[key], n.value, n.type, q.level + 1
from q
cross apply openjson(q.value) n
where q.type in (4,5)
)
select *, count(*) over (partition by path) pathCount
from q

SQL Server OPENJSON read nested json

I have some json that I would like to parse in SQL Server 2016. There is a hierarchy structure of Projects->Structures->Properties. I would like to write a query that parses the whole hierarchy but I don't want to specify any elements by index number ie I don't want to do anything like this:
openjson (#json, '$[0]')
or
openjson (#json, '$.structures[0]')
I had this idea that I could read the values of the top level project objects along with the json string that represents the structures below it, which could then be parsed separately. The problem is that the following code does not work:
declare #json nvarchar(max)
set #json = '
[
{
"IdProject":"97A76363-095D-4FAB-940E-9ED2722DBC47",
"Name":"Test Project",
"structures":[
{
"IdStructure":"CB0466F9-662F-412B-956A-7D164B5D358F",
"IdProject":"97A76363-095D-4FAB-940E-9ED2722DBC47",
"Name":"Test Structure",
"BaseStructure":"Base Structure",
"DatabaseSchema":"dbo",
"properties":[
{
"IdProperty":"618DC40B-4D04-4BF8-B1E6-12E13DDE86F4",
"IdStructure":"CB0466F9-662F-412B-956A-7D164B5D358F",
"Name":"Test Property 2",
"DataType":1,
"Precision":0,
"Scale":0,
"IsNullable":false,
"ObjectName":"Test Object",
"DefaultType":1,
"DefaultValue":""
},
{
"IdProperty":"FFF433EC-0BB5-41CD-8A71-B5F09B97C5FC",
"IdStructure":"CB0466F9-662F-412B-956A-7D164B5D358F",
"Name":"Test Property 1",
"DataType":1,
"Precision":0,
"Scale":0,
"IsNullable":false,
"ObjectName":"Test Object",
"DefaultType":1,
"DefaultValue":""
}
]
}
]
}
]';
select IdProject, Name, structures
from openjson (#json)
with
(
IdProject uniqueidentifier,
Name nvarchar(100),
structures nvarchar(max)
) as Projects
IdProject and Name get returned no problem but for some reason I cannot get the nested json held in 'structures'. Instead of the json content it just returns NULL:
Does anyone know if this is possible and if so, what am I doing wrong?
Using CROSS APPLY:
declare #json nvarchar(max)
set #json = '
[
{
"IdProject":"97A76363-095D-4FAB-940E-9ED2722DBC47",
"Name":"Test Project",
"structures":[
{
"IdStructure":"CB0466F9-662F-412B-956A-7D164B5D358F",
"IdProject":"97A76363-095D-4FAB-940E-9ED2722DBC47",
"Name":"Test Structure",
"BaseStructure":"Base Structure",
"DatabaseSchema":"dbo",
"properties":[
{
"IdProperty":"618DC40B-4D04-4BF8-B1E6-12E13DDE86F4",
"IdStructure":"CB0466F9-662F-412B-956A-7D164B5D358F",
"Name":"Test Property 2",
"DataType":1,
"Precision":0,
"Scale":0,
"IsNullable":false,
"ObjectName":"Test Object",
"DefaultType":1,
"DefaultValue":""
},
{
"IdProperty":"FFF433EC-0BB5-41CD-8A71-B5F09B97C5FC",
"IdStructure":"CB0466F9-662F-412B-956A-7D164B5D358F",
"Name":"Test Property 1",
"DataType":1,
"Precision":0,
"Scale":0,
"IsNullable":false,
"ObjectName":"Test Object",
"DefaultType":1,
"DefaultValue":""
}
]
}
]
}
]';
select
Projects.IdProject, Projects.Name as NameProject,
Structures.IdStructure, Structures.Name as NameStructure, Structures.BaseStructure, Structures.DatabaseSchema,
Properties.*
from openjson (#json)
with
(
IdProject uniqueidentifier,
Name nvarchar(100),
structures nvarchar(max) as json
)
as Projects
cross apply openjson (Projects.structures)
with
(
IdStructure uniqueidentifier,
Name nvarchar(100),
BaseStructure nvarchar(100),
DatabaseSchema sysname,
properties nvarchar(max) as json
) as Structures
cross apply openjson (Structures.properties)
with
(
IdProperty uniqueidentifier,
NamePreoperty nvarchar(100) '$.Name',
DataType int,
[Precision] int,
[Scale] int,
IsNullable bit,
ObjectName nvarchar(100),
DefaultType int,
DefaultValue nvarchar(100)
)
as Properties
If you reference JSON object or array you need to specify AS JSON clause:
select IdProject, Name, structures
from openjson (#json)
with
(
IdProject uniqueidentifier,
Name nvarchar(100),
structures nvarchar(max) AS JSON
) as Projects
See FAQ: https://learn.microsoft.com/en-us/sql/relational-databases/json/solve-common-issues-with-json-in-sql-server?view=sql-server-ver15#return-a-nested-json-sub-object-from-json-text-with-openjson
If you want to apply OPENJSON on the returned structures array, you can use something like following code:
select IdProject, Name, structures
from openjson (#json)
with
(
IdProject uniqueidentifier,
Name nvarchar(100),
structures nvarchar(max) AS JSON
) as Projects
CROSS APPLY OPENJSON (structures) WITH (......)
Typical! I found the answer just after posting the question. You need to use the 'as json' key word when specifying the columns to return:
select IdProject, Name, structures
from openjson (#json)
with
(
IdProject uniqueidentifier,
Name nvarchar(100),
structures nvarchar(max) as json
) as Projects