I am trying to concatenate nested JSON in SQL, how to do that.
Please help me out with this.
Example: I have JSON Like below.
[
{
"Name": "Cards",
"Value": [
"Pack of 24 Dare Cards"
],
"SourceSpecified": false,
"Any": []
},
{
"Name": "Boppers and Shot Glasses",
"Value": [
"12 Willy Shot Glass and 12 Hen Boppers"
],
"SourceSpecified": false,
"Any": []
}
]
I want Out Put:
Pack of 24 Dare Cards-12 Willy Shot Glass and 12 Hen Boppers
If Value always contains one element
DECLARE #JSON NVARCHAR(MAX) = ' [
{
"Name": "Cards",
"Value": [
"Pack of 24 Dare Cards"
],
"SourceSpecified": false,
"Any": []
},
{
"Name": "Boppers and Shot Glasses",
"Value": [
"12 Willy Shot Glass and 12 Hen Boppers"
],
"SourceSpecified": false,
"Any": []
}
]'
SELECT STRING_AGG(Val, '-')
FROM OPENJSON(#JSON)
WITH (Val NVARCHAR(MAX) '$.Value[0]')
Support of multiple values is also easy.
SELECT STRING_AGG(Val, '-')
FROM OPENJSON(#JSON)
WITH (VALUE NVARCHAR(MAX) '$.Value' AS JSON)
OUTER APPLY OPENJSON(VALUE) WITH (Val NVARCHAR(MAX) '$')
This one I achieved with creating a scalar-valued function to populate concatenated value.
Create FUNCTION [dbo].[test]
(
#VariationData nvarchar(max)
)
RETURNS nvarchar(max)
AS
BEGIN
Declare #val nvarchar(max)
select #val = COALESCE(#val+', ','')+ Value from OPENJSON(#VariationData)
With ([Value] NVARCHAR(MAX) N'$.Value[0]')
return #val
END
Call function with nested JSON value i.e
Select [dbo].[test] (#JSON);
This worked for me.
Related
I am trying to flatten nested array from JSON in SQL Server, using the code below, but without success.
Used JSON
'{
"shipmentDetails": {
"shipmentId": "JHVJD5627278788"
},
"shipmentStops": [
{
"stopSequence": 1,
"orderReferenceNumbers": [
"2120549020", "test"
]
},
{
"stopSequence": 2,
"orderReferenceNumbers": [
"2120549020", "2120549002"
]
}
]
}'
DECLARE #Step AS NVARCHAR(max) = N'Variables declaration';
DECLARE #JSON1 AS NVARCHAR(MAX);
SET #JSON1 = '{
"shipmentDetails": {
"shipmentId": "JHVJD5627278788"
},
"shipmentStops": [
{
"stopSequence": 1,
"orderReferenceNumbers": [
"2120549020", "test"
]
},
{
"stopSequence": 2,
"orderReferenceNumbers": [
"2120549020", "2120549002"
]
}
]
}'
IF OBJECT_ID('JSONPO2') IS NOT NULL
DROP TABLE JSONPO2
SET #Step = N'JSON data parsing and loading into JSONPO2 temp table'
SELECT DISTINCT ShipDetails.shipmentId AS shipmentId
,ShipmentStops.stopSequence AS stopSequence
,ShipmentStops.orderReferenceNumbers AS orderReferenceNumbers
INTO JSONPO2
FROM OPENJSON(#JSON1) WITH (
shipmentDetails NVARCHAR(MAX) AS JSON
,shipmentStops NVARCHAR(MAX) AS JSON
) AS [Data]
CROSS APPLY OPENJSON(shipmentDetails) WITH (shipmentId NVARCHAR(20)) AS ShipDetails
CROSS APPLY OPENJSON(shipmentStops) WITH (
stopSequence INT
,orderReferenceNumbers NVARCHAR(MAX) AS JSON
) AS ShipmentStops
CROSS APPLY OPENJSON(orderReferenceNumbers) WITH (orderReferenceNumbers VARCHAR(max))
AS orderReferenceNumbers
SELECT *
FROM JSONPO2
From the above code, I receive only two rows with a strange array
shipmentId
stopSequence
orderReferenceNumbers
JHVJD5627278788
1
[ "2120549020", "test" ]
JHVJD5627278788
2
[ "2120549020", "2120549002" ]
How to change the code to parse nested arrays and have four rows like below?
shipmentId
stopSequence
orderReferenceNumbers
JHVJD5627278788
1
2120549020
JHVJD5627278788
1
test
JHVJD5627278788
2
2120549020
JHVJD5627278788
2
2120549002
Appreciate any help :)
Your issue is when trying to expand the array using the WITH clause:
CROSS APPLY OPENJSON(orderReferenceNumbers)
WITH (orderReferenceNumbers VARCHAR(max)) AS orderReferenceNumbers
The JSON you are opening though has no property "orderReferenceNumbers", it is simply:
["2120549020", "test"]
So this is returning NULL. You'd see this in your select if you were selecting orderReferenceNumbers.orderReferenceNumbers rather than ShipmentStops.orderReferenceNumbers.
You don't need to use WITH if you are opening a simple JSON array of primitive types. The following query will return the output you are after:
DECLARE #JSON1 AS NVARCHAR(MAX) = N'{
"shipmentDetails": {
"shipmentId": "JHVJD5627278788"
},
"shipmentStops": [
{
"stopSequence": 1,
"orderReferenceNumbers": [
"2120549020", "test"
]
},
{
"stopSequence": 2,
"orderReferenceNumbers": [
"2120549020", "2120549002"
]
}
]
}';
SELECT sd.shipmentId,
ss.stopSequence,
orderReferenceNumber = orn.Value
FROM OPENJSON(#JSON1)
WITH(shipmentDetails NVARCHAR(MAX) AS JSON, shipmentStops NVARCHAR(MAX) AS JSON) AS d
CROSS APPLY OPENJSON(d.shipmentDetails)
WITH(shipmentId NVARCHAR(20)) AS sd
CROSS APPLY OPENJSON(d.shipmentStops)
WITH(stopSequence INT, orderReferenceNumbers NVARCHAR(MAX) AS JSON) AS ss
CROSS APPLY OPENJSON(orderReferenceNumbers) AS orn;
Example on db<>fiddle
As an aside, if you will only ever have one shipmentId in the JSON (which would make sense otherwise you'd end up with cross joins) you can simplify this slightly, and remove one of the OPENJSON()s:
SELECT d.shipmentId,
ss.stopSequence,
orderReferenceNumber = orn.Value
FROM OPENJSON(#JSON1)
WITH(ShipmentId NVARCHAR(20) '$.shipmentDetails.shipmentId',
shipmentStops NVARCHAR(MAX) AS JSON) AS d
CROSS APPLY OPENJSON(d.shipmentStops)
WITH(stopSequence INT, orderReferenceNumbers NVARCHAR(MAX) AS JSON) AS ss
CROSS APPLY OPENJSON(ss.orderReferenceNumbers) AS orn;
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;
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
I have this data in a table:
{ "keys": [ "00170000007u8uJ" ] }
I need to extract only the value 00170000007u8uJ in a SQL Server 2016 select query.
This should do it
declare #json nvarchar(max)=N'{ "keys": [ "00170000007u8uJ" ] }';
select [value] from openjson(json_query(#json, N'$.keys'));
If the JSON is in a table then like this
create table #temp_json(json_col nvarchar(max));
insert #temp_json(json_col) values (N'{ "keys": [ "00170000007u8uJ" ] }');
select [value]
from
#temp_json tj
cross apply
openjson(json_query(tj.json_col, N'$.keys'));
I'm trying to set the path for my OPENJSON function for the nested array, but it's not working. Tried different variations and examples/resources I found online and still cannot figure it out.
Any ideas?
EDIT:
To be clear, I know how to do this with CROSSAPPLY and other methods. My question is in regards on how to do this specifically with the OPENJSON function's path parameter if possible.
Here's my code:
DECLARE #json NVARCHAR(MAX);
SET #json = '
{
"orders": [
{
"id":"1",
"date":"7/4/2020",
"orderlines": [
{"id": "1", "amount": 100},
{"id": "2", "amount": 200}
]
},
{
"id":"2",
"date":"7/4/2020",
"orderlines": [
{"id": "3", "amount": 300},
{"id": "4", "amount": 400}
]
}
]
}
'
-- None of these return results. How do I specify the path to the "orderlines" array?
SELECT * FROM OPENJSON(#json,'$.orderlines');
SELECT * FROM OPENJSON(#json,'$.orderlines[1]');
SELECT * FROM OPENJSON(#json,'$.orders.orderlines');
SELECT * FROM OPENJSON(#json,'$.orders.orderlines[1]');
-- This works:
SELECT * FROM OPENJSON(#json,'$.orders');
You can use WITH and put a name on inside values and use CROSS APPLY to use them in another OPENJSON. Now you can have all inside objects together.
SELECT orderlines.id, orderlines.amount
FROM OPENJSON(#json, '$.orders') WITH (orderlines NVARCHAR(MAX) '$.orderlines' AS JSON) orders
CROSS APPLY OPENJSON(orders.orderlines) WITH (id INT '$.id', amount INT '$.amount') orderlines
Learn more here.
Also if need to get specific item in array:
SELECT * FROM OPENJSON(#json, '$.orders[0].orderlines[0]')
-- OR
SELECT JSON_VALUE(#json, '$.orders[0].orderlines[0].amount')
To make it clear for others who may be viewing this, the part of Iman Kazemi's response that was the answer was the following of what he wrote:
SELECT * FROM OPENJSON(#json, '$.orders[0].orderlines[0]')
I neglected to specify the index on the order's array.
Thanks again to Iman.
You can try the following:
SELECT *
FROM OPENJSON (#json, '$.orders')
WITH (
id INT '$.id',
[date] VARCHAR(10) '$.date',
orderlines_id1 INT '$.orderlines[0].id',
orderlines_amount1 MONEY '$.orderlines[0].amount',
orderlines_id2 INT '$.orderlines[1].id',
orderlines_amount2 MONEY '$.orderlines[1].amount'
) AS Orders
Please see the db<>fiddle here.