OpenJson - nested select? - sql

I need to import json data into an SQL table however there are some fields that I only want the numeric value from the list. Is there way to do a nested select using openjson?
I'm calling a stored procedure on a Microsoft SQL 2016 server from pyton and passing the json as a parameter.
Select * from OpenJson(#json)
WITH (id int 'strict $.id',
[Name] nvarchar(50) '$.name',
term_id nvarchar(max) as json,
phone nvarchar(20) '$.phone',
email nvarchar(50) '$.email',
street nvarchar(75) '$.street',
street2 nvarchar(75) '$.street2',
city nvarchar(50) '$.city',
zip nvarchar(20),
country_id nvarchar(max) as JSON)
The table has the following fields
ID, Name, Term_ID, Phone, Email, Street, Street2, Zip, City, Country_ID
see the json below. On the fields term_id and country_id I only want to pull the numeric value not the string.
[{
"id": 340,
"name": Joe,
"term_id": [
3,
"Net 30"
],
"phone": 123-456-7890,
"email": false,
"street": "Some Street",
"street2": false,
"zip": "01234",
"city": "SomeCity",
"country_id": [
1,
"United States"
]
}]

Related

Extract a JSON array items to a single column separated with comma

Struggling to find an answer to the below JSON problem. I would like to display the entire SKU/Quantity list in the "shipmentItems" array to their respective column with a comma-separated value. My example below only allows me to display the first SKU/quantity from the array but, my goal is to get all listed in the columns with comma-separated.
JSON example:
{"shipments": [
{
"shipmentId": 100003768,
"orderNumber": "9648219086",
"shipDate": "2021-10-28",
"serviceCode": "ups_ground",
"shipmentItems": [
{
"orderItemId": 1464643208,
"lineItemKey": "10322938560608",
"sku": "SCPXTSS-BAG-06",
"name": "SCOOP-PLATE-06 (1000ml)",
"weight": {
"value": 0,
"units": "ounces",
"WeightUnits": 1
},
"quantity": 1,
"unitPrice": 0,
"taxAmount": null
},
{
"orderItemId": 1464643207,
"lineItemKey": "10322938527840",
"sku": "SCPZRTS-TRAY-01",
"name": "Beef: Tray 3 (Fill 004)<br>",
"weight": {
"value": 60,
"units": "ounces",
"WeightUnits": 1
},
"quantity": 1,
"unitPrice": 102.72,
"taxAmount": null
}
],
"labelData": null,
"formData": null
}
]
}
SQL query I'm using:
DECLARE #JSON varchar(max)
SELECT #JSON = BulkColumn
FROM OPENROWSET (BULK 'C:\Users\XPS-LT\json\today\shipments_20211031.json', SINGLE_CLOB)
IMPORT
SELECT *
FROM OPENJSON (#JSON, '$.shipments')
WITH
(
[shipmentId] bigint,
[orderNumber] nvarchar(60),
[shipDate] date,
[serviceCode] nvarchar(30),
[sku] nvarchar(MAX) N'$.shipmentItems[0].sku',
[quantity] int N'$.shipmentItems[0].quantity'
)
;
The "shipmentItems" part of the input JSON is an array, so you need an AS JSON clause in the first explicit schema and an additional OPENJSON() call:
DECLARE #json nvarchar(max)
...
SELECT
j.[shipmentId], j.[orderNumber], j.[shipDate], j.[serviceCode],
a.[sku], a.[quantity]
FROM OPENJSON (#json, '$.shipments') WITH (
[shipmentId] bigint,
[orderNumber] nvarchar(60),
[shipDate] date,
[serviceCode] nvarchar(30),
[shipmentItems] nvarchar(max) AS JSON
) j
OUTER APPLY (
SELECT
STRING_AGG([sku], ',') WITHIN GROUP (ORDER BY [orderItemId]),
STRING_AGG([quantity], ',') WITHIN GROUP (ORDER BY [orderItemId])
FROM OPENJSON (j.shipmentItems) WITH (
[orderItemId] int '$.orderItemId',
[sku] nvarchar(max) '$.sku',
[quantity] int N'$.quantity'
)
) a ([sku], [quantity])
Result:
shipmentId orderNumber shipDate serviceCode sku quantity
100003768 9648219086 2021-10-28 ups_ground SCPZRTS-TRAY-01,SCPXTSS-BAG-06 1,1

Msg 13607, Level 16, State 4, Line 27

i'm pretty new here and i'm trying to parse my JSON but keep getting this error. i have the below query and every time i try running it i get an error, any chance i can get some help? My intended result will be for the data to be displayed on a normal sql grid and later to insert the data into a table with the below formatting.
Declare #json varchar(MAX) = '
{"stops":
{
"__type": "stop",
"__name": "stops",
"company_id": "xxx",
"actual_arrival": "20210910130000-0500",
"actual_departure": "20210910140000-0500",
"address": "123 noneyabizwax",
"appt_required": false,
"city_id": 144537,
"city_name": "LEWISBURG",
"state": "TN",
"zip_code": "37091",
"confirmed": false,
"driver_load_unload": "N",
"eta": "20210910122900-0500",
"eta_distance": 46,
"eta_late": false,
"eta_oor": false,
"order_id": "12345",
"planned_arrival_time": "20210910122900-0500",
"sched_arrive_early": "20210910130000-0500",
"status": "D",
"stop_type": "PU"
}';
select *
from OPENJSON ( #json )
With (
Type Varchar(50) '$stops.__type',
Name Varchar(50) '$stops.__name',
CompID Varchar(100) '$stops.company_id' ,
AcArrvl DATETIME '$stops.actual_arrival' ,
AcDprtr DATETIME '$stops.actual_departure',
Addrs Varchar (200) '$stops.address',
Appt Varchar(50) '$stops.appt_required',
CityID Varchar(50) '$stops.city_id',
City Varchar(200) '$stops.city_name',
State nvarchar(max) '$stops.state',
Zip int '$stops.zip_code',
Confirmed Varchar(50) '$stops.confirmed',
DrvrLd nvarchar(max) '$stops.driver_load_unload',
ETA DATETIME '$stops.eta',
ETADISTNC INT '$stops.eta_distance',
ETALate nvarchar(max) '$stops.eta_late',
ETAOOR nvarchar(max) '$stops.eta_oor',
OrderID INT '$stops.order_id',
PlnndArrvlTm DATETIME '$stops.planned_arrival_time',
SchdArrvEarly DATETIME '$stops.sched_arrive_early',
Status nvarchar(max) '$stops.status',
StopType Varchar(50) '$stops.stop_type',
[Stops] nvarchar(max) AS JSON
)
Declare #json varchar(MAX) = '
{"stops":
{
"__type": "stop",
"__name": "stops",
"company_id": "xxx",
"actual_arrival": "20210910130000-0500",
"actual_departure": "20210910140000-0500",
"address": "123 noneyabizwax",
"appt_required": false,
"city_id": 144537,
"city_name": "LEWISBURG",
"state": "TN",
"zip_code": "37091",
"confirmed": false,
"driver_load_unload": "N",
"eta": "20210910122900-0500",
"eta_distance": 46,
"eta_late": false,
"eta_oor": false,
"order_id": "12345",
"planned_arrival_time": "20210910122900-0500",
"sched_arrive_early": "20210910130000-0500",
"status": "D",
"stop_type": "PU"}
}';
WITH date_convert
AS
(
SELECT CONVERT(DATETIMEOFFSET,STUFF(STUFF(STUFF(STUFF(STUFF(STUFF(JSON_VALUE(#JSON, '$.stops.actual_arrival'),18,0,':'),13,0,':'),11,0,':'),9,0,' '),7,0,'-'),5,0,'-')) AcArrvl,
CONVERT(DATETIMEOFFSET,STUFF(STUFF(STUFF(STUFF(STUFF(STUFF(JSON_VALUE(#JSON, '$.stops.actual_departure'),18,0,':'),13,0,':'),11,0,':'),9,0,' '),7,0,'-'),5,0,'-')) AcDprtr,
CONVERT(DATETIMEOFFSET,STUFF(STUFF(STUFF(STUFF(STUFF(STUFF(JSON_VALUE(#JSON, '$.stops.eta'),18,0,':'),13,0,':'),11,0,':'),9,0,' '),7,0,'-'),5,0,'-')) ETA,
CONVERT(DATETIMEOFFSET,STUFF(STUFF(STUFF(STUFF(STUFF(STUFF(JSON_VALUE(#JSON, '$.stops.planned_arrival_time'),18,0,':'),13,0,':'),11,0,':'),9,0,' '),7,0,'-'),5,0,'-')) PlnndArrvlTm,
CONVERT(DATETIMEOFFSET,STUFF(STUFF(STUFF(STUFF(STUFF(STUFF(JSON_VALUE(#JSON, '$.stops.sched_arrive_early'),18,0,':'),13,0,':'),11,0,':'),9,0,' '),7,0,'-'),5,0,'-')) SchdArrvEarly
)
select Type, Name,CompID,date_convert.AcArrvl,date_convert.AcDprtr,Addrs,Appt,CityID,City,State,Zip,Confirmed,DrvrLd,date_convert.ETA,ETADISTNC,ETALate,ETAOOR,OrderID,date_convert.PlnndArrvlTm,
date_convert.SchdArrvEarly, Status,StopType
from date_convert,
OPENJSON (#json)
With (
Type Varchar(50) '$.stops.__type',
Name Varchar(50) '$.stops.__name',
CompID Varchar(100) '$.stops.company_id' ,
Addrs Varchar (200) '$.stops.address',
Appt Varchar(50) '$.stops.appt_required',
CityID Varchar(50) '$.stops.city_id',
City Varchar(200) '$.stops.city_name',
State nvarchar(max) '$.stops.state',
Zip int '$.stops.zip_code',
Confirmed Varchar(50) '$.stops.confirmed',
DrvrLd nvarchar(max) '$.stops.driver_load_unload',
ETADISTNC INT '$.stops.eta_distance',
ETALate nvarchar(max) '$.stops.eta_late',
ETAOOR nvarchar(max) '$.stops.eta_oor',
OrderID INT '$.stops.order_id',
Status nvarchar(max) '$.stops.status',
StopType Varchar(50) '$.stops.stop_type'
)
It looks a little complicated but I've included an explanation below:
Add } (curly bracket) at the end of this line "stop_type": "PU"
You must add . (dot) after every $ sign in your With clause.
Then we need to remove [Stops] nvarchar(max) AS JSON line because you don't need to open another JSON object and also don't forget to remove a ,(comma) after StopType Varchar(50) '$.stops.stop_type,'
We need to convert your 5 date strings into at least a partially human readable format. To do this we need to use CONVERT() with STUFF() function. I could have converted all 5 strings in SELECT statment but because it would looks ugly I decided to do this in CTE (I named CTE as a date_convert)
Because we store our converted dates in CTE we don't need them in your With clause. So we delete them.
In order to see our converted dates with the rest of columns in one table we need to add CTE's name into FROM clause. After it's done we have to add name of each column both from your With clause and from CTE to SELECT statment. The order is not important but I've preserved the order from your original question.
https://dbfiddle.uk/?rdbms=sqlserver_2016&fiddle=5b3915d8df86127e1f3c84d0a9880e31

How to add a JSON value read from a parent JSON in a table column in SQL Server?

I'm trying to read a JSON and insert the values into a table. Among those values, there is one another JSON object. I'm trying to insert that JSON value into a column, but my code inserts nothing.
Here's what I tried so far:
DROP TABLE IF EXISTS #tmp
DECLARE #json NVARCHAR(MAX);
SET #json = N'[
{"id": 2, "info": {"name": "John", "surname": "Smith"}, "age": 25},
{"id": 5, "info": {"name": "Jane", "surname": "Smith"}, "dob": "2005-11-04T12:00:00"}
]';
SELECT [id], [info]
INTO #tmp
FROM OPENJSON(#json)
WITH
(
[id] NVARCHAR(100),
[info] NVARCHAR(max)
);
SELECT * FROM #tmp
This is the result I get:
id info
--------------
2 NULL
5 NULL
If I understand your problem correctly, you need to use AS JSON option as is mentioned in the documentation:
Use the AS JSON option in a column definition to specify that the
referenced property contains an inner JSON object or array. If you
specify the AS JSON option, the type of the column must be
NVARCHAR(MAX).
Statement:
DECLARE #json NVARCHAR(MAX);
SET #json = N'[
{"id": 2, "info": {"name": "John", "surname": "Smith"}, "age": 25},
{"id": 5, "info": {"name": "Jane", "surname": "Smith"}, "dob": "2005-11-04T12:00:00"}
]';
SELECT [id], [info]
INTO #tmp
FROM OPENJSON(#json) WITH (
[id] NVARCHAR(100) '$.id',
[info] NVARCHAR(max) '$.info' AS JSON
);
Result:
id info
2 {"name": "John", "surname": "Smith"}
5 {"name": "Jane", "surname": "Smith"}

Parsing JSON data to find one element

I'm sifting through a JSON movie database and can get most of the data without a problem. For each film, I've put the raw JSON in an nvarchar(max) column called jsondata, then added other columns to populate for indexing and quick retrieval purposes.
With my UPDATE statement, I'm able to populate all columns except for one, in which I need to parse through and find an element.
Here's an example of the JSON:
{
"title": "Amnesia Love",
"genres": [{
"id": 35,
"name": "Comedy"
}],
"id": 508989,
"original_language": "tl",
"overview": "A guy is trying to discover his true identity after being found unconscious in a remote island.",
"popularity": 2.583,
"release_date": "2018-02-28",
"credits": {
"cast": [{
"cast_id": 2,
"character": "",
"credit_id": "5a9af6ecc3a3680b7d024627",
"gender": 0,
"id": 1230955,
"name": "Paolo Ballesteros",
"order": 1,
"profile_path": "/8Cey11JPMWBCGuIcKBXvb6OQ7Je.jpg"
},
{
"cast_id": 3,
"character": "",
"credit_id": "5a9af6f3c3a3680b57024465",
"gender": 0,
"id": 1166094,
"name": "Yam Concepcion",
"order": 2,
"profile_path": "/fiPaXTkq440VHXDqlMRHtOpoLWT.jpg"
}],
"crew": [{
"credit_id": "5a9af6cc0e0a260649024c6a",
"department": "Directing",
"gender": 0,
"id": 1989658,
"job": "Director",
"name": "Albert Langitan",
"profile_path": null
},
{
"credit_id": "5a9af6dec3a3680b2d01f152",
"department": "Writing",
"gender": 0,
"id": 1989658,
"job": "Screenplay",
"name": "Albert Langitan",
"profile_path": null
}]
},
}
Here's the table schema:
CREATE TABLE dbo.moviedb(
id int IDENTITY(1,1) NOT NULL,
jsondata nvarchar(max) NULL,
title nvarchar(200) NULL,
movie_id varchar(255) NULL,
original_language char(2) NULL,
overview nvarchar(1000) NULL,
popularity float NULL,
release_date datetime NULL,
genre nvarchar(100) NULL,
director nvarchar(100)
)
Here is an update statement to populate the columns:
UPDATE t
SET t.title = j.title, t.movie_id = j.id, t.original_language = j.original_language,
t.overview = j.overview, t.popularity = j.popularity, t.release_date = j.release_date,
t.genre = ISNULL(JSON_VALUE(t.jsondata,'$.genres[0].name'),''),
t.director = JSON_VALUE(t.jsondata,'$.credits.crew[0].name')
FROM tmdb t
CROSS APPLY OPENJSON(jsondata)
WITH(title nvarchar(200), id int, original_language char(2), overview nvarchar(max),
popularity float, release_date datetime,
genres nvarchar(max) as JSON,
credits nvarchar(max) as JSON
) AS j
My problem is getting the director name. Since within $.credits, there are cast and crew elements, and within those, potentially many entries each - I'm not clear how to parse through via JSON_QUERY or using CROSS APPLY to basically say, 'find the $.credits.crew.job = "Director", then give me the $.credits.crew.name'.
Ok, after the comments, I think I've got it now. I use OUTER APPLY for the Director, since I still want to get the movie info even if no Director is specified. This lead me to one other issue - when there was more than 1 Director on the movie. But I think I can deal with that.
UPDATE t
SET t.title = j.title, t.movie_id = j.id, t.original_language = j.original_language,
t.overview = j.overview, t.popularity = j.popularity, t.release_date = j.release_date,
t.genre = ISNULL(JSON_VALUE(t.jsondata,'$.genres[0].name'),''),
t.director = k.name
FROM tmdb t
CROSS APPLY OPENJSON(jsondata)
WITH (title nvarchar(200), id int, original_language char(2),
overview nvarchar(max), popularity float, release_date datetime,
credits nvarchar(max) as JSON
) AS j
OUTER APPLY OPENJSON(j.credits,'$.crew')
WITH (job nvarchar(50), name nvarchar(100)) AS k
WHERE k.job = 'Director' OR k.job IS NULL

Json functions in SQL Server 2016

Here is my JSON
[{
"type": "FormBlock",
"id": "07bac163-1765-1fee-dba7-6668f8d8507f",
"x": 50,
"y": 57,
"width": 120,
"height": 50,
"alpha": 1,
"angle": 0,
"userData": {
"schema":"{"form":[{"id":"1493828935122"},{"id":"1495115355556"}]
}]
My query
SELECT JSON_VALUE((SELECT JSON_QUERY([Schema].[schema],'$[0]')
FROM [dbo].[Schema] WHERE objecttype='test'),'$.userData.schema.form[0].id')
[Schema].[schema] : Table [Schema] with column [schema] (contain a json)
I can get userData.schema data, but if i want to have userData.schema.form.id it doesn't want to work. Why?
Assume you have the following document stored in SQL:
CREATE TABLE JSONTable (
ID int IDENTITY (1,1) PRIMARY KEY CLUSTERED
,JSONDocument nvarchar(max) )
INSERT INTO JSONTable
SELECT '{
"FilmDetails":{
"ProductNumber":"9912088751",
"Title":"Brave",
"Type":"Movie",
"Runtime":93,
"ReleaseYear":2012,
"Synopses":[
{
"Locale":"en",
"Text":"Princess Merida uses her bravery and archery skills to battle a curse and restore peace..."
},
{
"Locale":"de",
"Text":"Animiert"
},
{
"Locale":"fr",
"Text":"Au coeur des contrées sauvages dÉcosse, Merida, la fille du roi Fergus et de la reine Elinor..."}],
"Assets":[
{
"Name":"Stickers",
"AssetType":"Stickers",
"FileType":"PDF",
"Location":"http://media.brave.stickers.pdf",
"Locale":"en-US"
},
{
"Name":"Trailer - WMV",
"AssetType":"Trailer - WMV",
"FileType":"Video",
"Location":"http://youtu.be/Shg79Shgn",
"Locale":"en-US"
}]
}
}'
You can query in to arrays like such:
SELECT
JSON_VALUE(JSONDocument, '$.FilmDetails.ProductNumber') as ProductNumber
,JSON_VALUE(JSONDocument, '$.FilmDetails.Title') as Title
,JSON_VALUE(JSONDocument, '$.FilmDetails.Type') as ContentType
,JSON_VALUE(JSONDocument, '$.FilmDetails.Runtime') as Runtime
,JSON_VALUE(JSONDocument, '$.FilmDetails.ReleaseYear') as ReleaseYear
,Locale
,SynopsesText
,Name AS AssetName
,FileType AS AssetFileType
,[Location] AS AssetLocation
FROM JSONTable
CROSS APPLY OPENJSON(JSONDocument, '$.FilmDetails.Synopses')
WITH (
Locale varchar(3) '$.Locale'
,SynopsesText nvarchar(2000) '$.Text')
CROSS APPLY OPENJSON(JSONDocument, '$.FilmDetails.Assets')
WITH (
Name varchar(25) '$.Name'
,FileType varchar(25) '$.FileType'
,[Location] nvarchar(500) '$.Location' )
WHERE JSON_VALUE(JSONDocument, '$.FilmDetails.Title') LIKE '%Brave%'
AND Locale = 'en'
AND FileType = 'video'
This is from a blog post I made awhile back, but I think it gives you what you are looking for, querying in to arrays.