SQL Server JSON Array - arrays
I have some JSON that I would like to parse in SQL Server 2016. There is a hierarchy structure with arrays. I would like to write a query that parses the whole hierarchy more efficiently, I have challenges trying to access embedded arrays especially anything under "DealerPrefLocation", while I have no problems accessing anything under "DealerInformation", below is my sample JSON:
{
"DealerInformation": {
"Altername": [
{
"firstName": "two",
"lastName": "one",
"middleName": null,
"otherNameExplanation": "change"
}
],
"DealerType": {
"id": "87ab-098ng-2345li",
"name": "DMD"
},
"firstName": "PK",
"middleName": null,
"lastName": "KPK",
"primaryDealerState": "AP",
"otherDealerState": [
"AP",
"MP"]
},
"DealerPrefLocation": [
{
"PrefLocation": [
{
"address": {
"address1": "fort warangal",
"address2": "east",
"addressStandardizationSource": null,
"city": "warangal",
"country": "India"
},
"apptPhoneNumber": "989898989898",
"createdAt": null,
"phoneNumber": "989898989898"
}
],
"NonPrefLocation": [
{
"address": {
"address1": "fort Junction",
"address2": null,
"addressStandardizationSource": null
},
"createdAt": null,
"ServiceName": "H1",
"ServiceId": [
{
"ServiceGroupName": null,
"Type": "GROUP",
"ServiceNumber": "9999999"
}
]
}
],
"Inserted": null,
"Updated": null }
]
}
I did figure out how to query "DealerInformation" and arrays within it such as "AlterName" and "OtherDealerState", however I have challenges querying arrays under "DealerInformation"-->"PrefLocation"-->Address.
Please find my current query and output:
select
ID,
JSON_VALUE(VALUE_ID,'$.DealerInformation.firstName'),
JSON_VALUE(VALUE_ID,'$.DealerInformation.primaryDealerState'),
JSON_VALUE(A.VALUE,'$.firstName'),
JSON_VALUE(C.VALUE,'$.PrefLocation.address.address1')
from
Test_JSON_File
cross apply
openjson(Test_JSON_File.value_id,'$.DealerInformation.Altername')A
cross apply
openjson(Test_JSON_File.Test_JSON_CAQH.value_id,'$.DealerPrefLocation')C
The last column I selected is from "DealerPrefLocation" but I get only nulls, can someone help what am I missing in the SQL or what do I need to add?
Sorry, this answer is rather late...
I think, the most important information for you is the AS JSON within the WITH-clause. See how I use it:
DECLARE #json NVARCHAR(MAX) =
N' {
"DealerInformation": {
"Altername": [
{
"firstName": "two",
"lastName": "one",
"middleName": null,
"otherNameExplanation": "change"
}
],
"DealerType": {
"id": "87ab-098ng-2345li",
"name": "DMD"
},
"firstName": "PK",
"middleName": null,
"lastName": "KPK",
"primaryDealerState": "AP",
"otherDealerState": [
"AP",
"MP"]
},
"DealerPrefLocation": [
{
"PrefLocation": [
{
"address": {
"address1": "fort warangal",
"address2": "east",
"addressStandardizationSource": null,
"city": "warangal",
"country": "India"
},
"apptPhoneNumber": "989898989898",
"createdAt": null,
"phoneNumber": "989898989898"
}
],
"NonPrefLocation": [
{
"address": {
"address1": "fort Junction",
"address2": null,
"addressStandardizationSource": null
},
"createdAt": null,
"ServiceName": "H1",
"ServiceId": [
{
"ServiceGroupName": null,
"Type": "GROUP",
"ServiceNumber": "9999999"
}
]
}
],
"Inserted": null,
"Updated": null }
]
}';
--I'll pick at least one element out of each region. This should point you the way:
SELECT B.firstName
,B.middleName
,B.lastName
,JSON_VALUE(B.DealerType,'$.id') AS DealerTypeId
,B.PrimaryDealerState
,B.otherDealerState --You can dive deeper to parse that array
,JSON_VALUE(B.Altername,'$[0].firstName') AS Alter_firstName --there might be more...
,JSON_VALUE(C.PrefLocation,'$[0].address.address1') AS pref_address --there might be more...
,JSON_VALUE(C.PrefLocation,'$[0].apptPhoneNumber') AS pref_apptPhoneNumber
,JSON_VALUE(C.NonPrefLocation,'$[0].address.address1') AS nonpref_address --there might be more...
,JSON_VALUE(C.NonPrefLocation,'$[0].ServiceName') AS nonpref_ServiceName
FROM OPENJSON(#json)
WITH(DealerInformation NVARCHAR(MAX) AS JSON
,DealerPrefLocation NVARCHAR(MAX) AS JSON) A
OUTER APPLY OPENJSON(A.DealerInformation)
WITH(Altername NVARCHAR(MAX) AS JSON
,DealerType NVARCHAR(MAX) AS JSON
,firstName NVARCHAR(MAX)
,DealerType NVARCHAR(MAX) AS JSON
,middleName NVARCHAR(MAX)
,lastName NVARCHAR(MAX)
,primaryDealerState NVARCHAR(MAX)
,otherDealerState NVARCHAR(MAX) AS JSON) B
OUTER APPLY OPENJSON(A.DealerPrefLocation)
WITH(PrefLocation NVARCHAR(MAX) AS JSON
,NonPrefLocation NVARCHAR(MAX) AS JSON) C
UPDATE Select out of a table
Try this
SELECT B.firstName
,B.middleName
,B.lastName
,JSON_VALUE(B.DealerType,'$.id') AS DealerTypeId
,B.PrimaryDealerState
,B.otherDealerState --You can dive deeper to parse that array
,JSON_VALUE(B.Altername,'$[0].firstName') AS Alter_firstName --there might be more...
,JSON_VALUE(C.PrefLocation,'$[0].address.address1') AS pref_address --there might be more...
,JSON_VALUE(C.PrefLocation,'$[0].apptPhoneNumber') AS pref_apptPhoneNumber
,JSON_VALUE(C.NonPrefLocation,'$[0].address.address1') AS nonpref_address --there might be more...
,JSON_VALUE(C.NonPrefLocation,'$[0].ServiceName') AS nonpref_ServiceName
FROM Test_JSON_File
CROSS APPLY OPENJSON(value_id)
WITH(DealerInformation NVARCHAR(MAX) AS JSON
,DealerPrefLocation NVARCHAR(MAX) AS JSON) A
OUTER APPLY OPENJSON(A.DealerInformation)
WITH(Altername NVARCHAR(MAX) AS JSON
,DealerType NVARCHAR(MAX) AS JSON
,firstName NVARCHAR(MAX)
,DealerType NVARCHAR(MAX) AS JSON
,middleName NVARCHAR(MAX)
,lastName NVARCHAR(MAX)
,primaryDealerState NVARCHAR(MAX)
,otherDealerState NVARCHAR(MAX) AS JSON) B
OUTER APPLY OPENJSON(A.DealerPrefLocation)
WITH(PrefLocation NVARCHAR(MAX) AS JSON
,NonPrefLocation NVARCHAR(MAX) AS JSON) C;
Related
In Snowflake, how do I select directly from a json variable?
How can I build a select statement in Snowflake where I am selecting directly from a json variant variable, instead of a column in a table? My json is just an array of objects, and I will want to select the properties as columns. I see tons of examples of using flatten on a variant column, but can't figure out how to select directly from a variable without a table and column. var_input := ' [ { "Name": "Avinash Gupta", "Relationship": "Father", }, { "Name": "Lata Gupta", "Relationship": "Mother", }, { "Name": "Shrishti Gupta", "Relationship": "Sister", }, { "Name": "Bobin Gupta", "Relationship": "Brother", } ]' ;
It is perfectly possible, to access variable in SELECT. Example below: BEGIN LET var_input VARIANT := '[ { "Name": "Avinash Gupta", "Relationship": "Father", }, { "Name": "Lata Gupta", "Relationship": "Mother", }, { "Name": "Shrishti Gupta", "Relationship": "Sister", }, { "Name": "Bobin Gupta", "Relationship": "Brother", } ]'; -- materializing the output as temporary table for simplicity CREATE OR REPLACE TEMPORARY TABLE t AS SELECT f.value:Name::TEXT AS name FROM TABLE(FLATTEN(INPUT => PARSE_JSON(:var_input))) AS f; END; SELECT * FROM t; Output:
Parse JSON file - Improve query in SQL Server
From this JSON File (just an example) I need to reach this final result { "Id": "101", "name": "C01", "testparameters": { "room": [ { "Floor": "First_Floor", "Rooms": ["Room1", "Room2", "Room3"] }, { "Floor": "Second_Floor", "Rooms": ["Room1", "Room2", "Room3"] } ], "area": [ { "Name": "Area1", "Subarea": ["Subarea1", "Subarea2", "Subarea3"] }, { "Name": "Area2", "Subarea": ["Subarea4", "Subarea5"] } ], "requirements": [{ "condition": "", "type": "type1", "field1": "", "field2": "aaaaa", "operator": "", "value2": "" }, { "condition": "AND", "type": "type2", "field1": "", "field2": "numPersons", "operator": ">", "value2": "20" }, { "condition": "OR", "type": "type2", "field1": "", "field2": "specification", "operator": "=", "value2": "wifi" } ] } } ' In one register I need to have all the information that is requested. This is the first time that I need to parse a JSON file. After asking (a lot) I manage to reach the expected result by doing this: Parsing JSON Example However, I had to open the JSON file several times, and process each section apart. I'm wondering, how can I improve the code by reducing the number of times that I need to use the OPENJSON function, and in particular, how to rewrite the code snippet that handle the requirements section.
I must say, your desired result looks pretty de-normalized, you may want to rethink it. Be that as it may, you can combine these quite easily, by using nested subqueries SELECT ID = JSON_VALUE(j.json, '$.Id'), name = JSON_VALUE(j.json, '$.name'), area = ( SELECT STRING_AGG(concat(d.a , ':', b.value),' - ') from openjson(j.json, '$.testparameters.area') with ( a nvarchar(250) '$.Name', s nvarchar(max) '$.Subarea' as json ) as d cross apply openjson(d.s) as b ), room = ( SELECT STRING_AGG(concat(c.f, ':', d.value), ' - ') from openjson(j.json, '$.testparameters.room') with( f nvarchar(50) '$.Floor', r nvarchar(Max) '$.Rooms' as json ) as c cross apply openjson(c.r) as d ), requirements = ( SELECT IIF( SUBSTRING(requirements,1,3) = 'AND' or SUBSTRING(requirements,1,3) = 'OR', SUBSTRING(requirements,5,LEN(requirements)), requirements ) from ( select STRING_AGG(CONCAT_WS(' ', a.condition, a.field2, operator, IIF (ISNUMERIC(a.value2) = 1, a.value2, CONCAT('''',a.value2,'''') ) ), ' ') as requirements from openjson(j.json, '$.testparameters.requirements' ) with ( condition nvarchar(255) '$.condition', type nvarchar(255) '$.type', field2 nvarchar(255) '$.field2', operator nvarchar(255) '$.operator', value2 nvarchar(255) '$.value2' ) a where a.type = 'type2' ) a ) FROM (VALUES(#json)) AS j(json) -- or you can reference a table
Get values from JSON - SQL Server
I have the following JSON: [ { "email_id": 1598819368, "email": "test01#abc.net" }, { "email_id": 1598819369, "email": "test02#abc.net" }, { "email_id": 1598819370, "email": "test03#abc.net" }, { "email_id": 1598819371, "email": "test04#abc.net" } ] How do I return a list of just the email addresses using SQLServer 2017? ------------------- emailaddress ------------------- test01#abc.net test02#abc.net test03#abc.net test04#abc.net I've been trying to use JSON_VALUE or JSON_QUERY but I either only get one email address or NULLs. Thank you!
This should do it declare #json nvarchar(max)=N'[ { "email_id": 1598819368, "email": "test01#abc.net" }, { "email_id": 1598819369, "email": "test02#abc.net" }, { "email_id": 1598819370, "email": "test03#abc.net" }, { "email_id": 1598819371, "email": "test04#abc.net" } ]' select email from openjson(#json) with (email_id bigint, email nvarchar(200)); Results email test01#abc.net test02#abc.net test03#abc.net test04#abc.net
How can i do a join with a GEOJson file and a table that exists already in the database?
I have a file with GEOJson data like so: { "type": "FeatureCollection", "features": [ { "type": "Feature", "geometry": { "type": "Polygon", "coordinates": [ [ [-73.759739, 42.61379], [-73.759565, 42.614179], [-73.752172, 42.614284999999995], [-73.744867, 42.617281], [-73.743042, 42.628958999999995], [-73.74260799999999, 42.631581999999995], [-73.734443, 42.631879999999995], [-73.733936, 42.632020999999995], [-73.73479499999999, 42.636396], [-73.73097299999999, 42.643890999999996], [-73.759739, 42.61379] ], [[-73.72579, 42.650059], [-73.725143, 42.649788], [-73.725071, 42.649817], [-73.724823, 42.650282999999995], [-73.72552499999999, 42.650486], [-73.72579, 42.650059]] ] }, "properties": { "STATEFP": "36", "UNSDLEA": "09630", "AFFGEOID": "9700000US3609630", "GEOID": "3609630", "NAME": "East Greenbush Central School District", "LSAD": "00", "ALAND": 195779723, "AWATER": 2721773 } }, { "type": "Feature", "geometry": { "type": "MultiPolygon", "coordinates": [ [[[-73.64970199999999, 42.351976], [-73.647074, 42.352069], [-73.647874, 42.353819], [-73.644886, 42.353538], [-73.640999, 42.354502], [-73.640935, 42.350439], [-73.64918399999999, 42.350263], [-73.64970199999999, 42.351976]]], [ [ [-73.65831, 42.392008], [-73.656461, 42.394642], [-73.656983, 42.398876], [-73.653469, 42.398039999999995], [-73.65123799999999, 42.396592], [-73.647519, 42.395765], [-73.64356599999999, 42.392081], [-73.649436, 42.392233], [-73.652639, 42.393062], [-73.65522, 42.39261], [-73.655879, 42.390594], [-73.658508, 42.391143], [-73.65831, 42.392008] ] ], [ [ [-73.77776399999999, 42.424766999999996], [-73.775817, 42.429938], [-73.774451, 42.435269], [-73.77367, 42.44404], [-73.773833, 42.449467999999996], [-73.77420099999999, 42.451465999999996], [-73.77553499999999, 42.451522999999995], [-73.776663, 42.452602999999996], [-73.77599, 42.454141], [-73.777172, 42.455293999999995], [-73.77776399999999, 42.424766999999996] ] ] ] }, "properties": { "STATEFP": "36", "UNSDLEA": "15210", "AFFGEOID": "9700000US3615210", "GEOID": "3615210", "NAME": "Kinderhook Central School District (Ichabod Crane)", "LSAD": "00", "ALAND": 202445671, "AWATER": 9611722 } } ] } How I can do a join where I can select the entire record E.g. { "type": "Feature", "geometry": { "type": "Polygon", "coordinates": [ [ [-73.759739, 42.61379], [-73.759565, 42.614179], [-73.752172, 42.614284999999995], [-73.744867, 42.617281], [-73.743042, 42.628958999999995], [-73.74260799999999, 42.631581999999995], [-73.734443, 42.631879999999995], [-73.733936, 42.632020999999995], [-73.73479499999999, 42.636396], [-73.73097299999999, 42.643890999999996], [-73.759739, 42.61379] ], [[-73.72579, 42.650059], [-73.725143, 42.649788], [-73.725071, 42.649817], [-73.724823, 42.650282999999995], [-73.72552499999999, 42.650486], [-73.72579, 42.650059]] ] }, "properties": { "STATEFP": "36", "UNSDLEA": "09630", "AFFGEOID": "9700000US3609630", "GEOID": "3609630", "NAME": "East Greenbush Central School District", "LSAD": "00", "ALAND": 195779723, "AWATER": 2721773 } } where the name property from the file matches name column from my table?? My table is like so: CREATE TABLE SCHOOL_INFO ( [id] [int] IDENTITY(1,1) NOT NULL, [name] [varchar](128) NOT NULL, [address] [varchar](128) NOT NULL, [city] [varchar](128) NOT NULL, [state] [varchar](128) NOT NULL, [zip] [varchar](16) NOT NULL, [jsondata] [varchar](MAX) NOT NULL ) All I want to do is insert the insert the matching json data into the jsondata column as a string. I do not need to use any of SQL spatial capabilities. I figured out the following SQL: Declare #JSON varchar(max) SELECT #JSON = BulkColumn FROM OPENROWSET (BULK 'C:\temp\nyusd.json', SINGLE_CLOB) as j SELECT * FROM OPENJSON (#JSON, '$.features') I tried to query for one record using the following SQL but I think I have the syntax wrong: Declare #JSON varchar(max) SELECT #JSON = BulkColumn FROM OPENROWSET (BULK 'C:\temp\nyusd.json', SINGLE_CLOB) as j SELECT * FROM OPENJSON (#JSON, '$.features') where JSON_VALUE(#JSON, '$.features.properties.Name') = 'East Greenbush Central School District'; Can someone point me in the right direction? Thanks!
Please try: Declare #JSON nvarchar(max) SELECT #JSON = BulkColumn FROM OPENROWSET (BULK 'C:\temp\nyusd.json', SINGLE_CLOB) as j select * From ( SELECT * FROM OPENJSON (#JSON, '$.features') )x WHERE JSON_VALUE(x.[value], '$.properties.NAME') = 'East Greenbush Central School District'
Nest Json Array merge
I have a column saved json data in my table: declare #json nvarchar(max) set #json = N' { "Companies": [ { "CompanyId": "A", "Employee": null }, { "CompanyId": "B", "Employee": [ { "EmployeePictureId": null, "Name": "Employee1" }, { "EmployeePictureId": "PictureId2", "Name": "Employee2" } ] }, { "CompanyId": "C", "Employee": [ { "EmployeePictureId": null, "Name": "Employee3" }, { "EmployeePictureId": null, "Name": "Employee4" } ] } ] } ' Is it posible to get the result like: { "EmployeePictureIds": ["PictureId2"] } using the Json_Query, Json_Value, OPENJSON... Only get EmployeePictureId and skip empty(null) data By the way, the count of elements in array are not sure.
In SQL Server 2017 you can use the following query: select json_query(QUOTENAME(STRING_AGG('"' + STRING_ESCAPE( A.EmployeePictureId , 'json') + '"', char(44)))) as [EmployeePictureIds] FROM OPENJSON(#json, '$.Companies') WITH ( CompanyId NVARCHAR(MAX), Employee NVARCHAR(MAX) as json ) as B cross apply openjson (B.Employee) with ( EmployeePictureId VARCHAR(50), [Name] VARCHAR(50) ) as A where A.EmployeePictureId is not null for json path , WITHOUT_ARRAY_WRAPPER Results for the JSON you provided: Results adding another non null EmployeePictureId: