Remove array from json object stored in SQL Server column - json

If I have the following JSON stored in a column in SQL Server:
declare #json nvarchar(max) = '[{"id": "1", "name": "test1"},{"id": "2", "name": "test2"},{"id": "3", "name": "test4"}]'
how can I remove an array where Id:=1 ?
I want to get the following result:
[{"id": "2", "name": "test2"},{"id": "3", "name": "test4"}]

try this:
declare #json nvarchar(max) = '[{"id": "1", "name": "test1"},{"id": "2", "name": "test2"},{"id": "3", "name": "test4"}]';
DECLARE #IdTobeRemoved INT =1;
DECLARE #StartIndex INT
DECLARE #EndIndex INT
DECLARE #tempjson nvarchar(max)
SELECT #StartIndex = CHARINDEX('"id": "'+CONVERT(VARCHAR(10),#IdTobeRemoved)+'"',#json)-2
SELECT #tempjson = STUFF(#json, 1, #StartIndex, '')
SELECT #EndIndex =
CASE WHEN SUBSTRING(#tempjson,CHARINDEX('}',#tempjson)+1,1)=']'
THEN CHARINDEX('}',#tempjson)+1
ELSE CHARINDEX('}',#tempjson)+2
END
SELECT REPLACE(REPLACE(#json,SUBSTRING(#tempjson,0,#EndIndex),''),'},]','}]')

Related

Parse JSON document into table

I'm working on parsing JSON document with an object array into a SQL Server table. I'm stuck with how to parse the complex object array.
I tried subproject.id and that did not work. I usually use the below code to parse a JSON array which works just fine but in this case it does not.
JSON:
{
"Data": [
{
"name": "ABC",
"date": "2020-01-20",
"subproject": [
{
"id": "123",
"projectname": "new1",
"refnum": "123:new1"
},
{
"id": "456",
"projectname": "new2",
"refnum": "456:new2"
}
],
"projectid": "1234",
"projectdate": "2020-01-27"
},
{
"name": "DEF",
"date": "2020-01-30",
"subproject": [
{
"id": "789",
"projectname": "new3",
"refnum": "789:new3"
},
{
"id": "901",
"projectname": "new4",
"refnum": "901:new4"
}
],
"projectid": "4567",
"projectdate": "2020-02-07"
}
]
}
SQL:
DECLARE #JSON VARCHAR(MAX)
SELECT #JSON = BulkColumn
FROM OPENROWSET (BULK 'c:/data/project.json', SINGLE_CLOB) X
SELECT *
FROM OPENJSON (#JSON)
WITH (
[name] NVARCHAR(256),
[date] DATE,
[projectid] INT,
[projectdate] DATE
)
You need to use AS JSON clause in the first OPENJSON() call (to specify that the $.subproject property contains an inner JSON array) and a combination of another OPENJSON() call and APPLY operator:
SELECT *
FROM OPENJSON (#JSON, '$.Data') WITH (
[name] NVARCHAR(256),
[date] DATE,
[projectid] INT,
[projectdate] DATE,
[subproject] NVARCHAR(MAX) '$.subproject' AS JSON
) j1
OUTER APPLY OPENJSON (j1.[subproject]) WITH (
[subprojectid] INT '$.id',
[subprojectname] NVARCHAR(256) '$.projectname',
[subprojectrefnum] NVARCHAR(256) '$.refnum'
) j2

Remove elements from a JSON array, with no key

I'm looking for a way that I can remove elements from a JSON array in SQL Server, I tried using JSON_MODIFY/OPENPATH, but I can't seem to get the path parameter correct.
Here is an example of what I want to do is convert:
[{"FieldName":"OrderStatusTypeId","FieldType":"Int32","ValueBefore":"8","ValueAfter":"10","Action":2},{"FieldName":"PatientReferenceNumber","FieldType":"String","ValueBefore":"","ValueAfter":"","Action":2}]
To be:
[{"FieldName":"OrderStatusTypeId","FieldType":"Int32","ValueBefore":"8","ValueAfter":"10","Action":2}]
Basically, I want to remove any element of the array, whereby the Action is 2 and the ValueBefore and the ValueAfter fields are the same.
Here is what I'm attempting at the moment, as a test, but I keep getting the error below:
DECLARE #JSONData AS NVARCHAR(4000)
SET #JSONData = N'[{"FieldName":"OrderStatusTypeId","FieldType":"Int32","ValueBefore":"8","ValueAfter":"10","Action":2},{"FieldName":"PatientReferenceNumber","FieldType":"String","ValueBefore":"","ValueAfter":"","Action":2},{"FieldName":"PoNumber","FieldType":"String","ValueBefore":"","ValueAfter":"","Action":2},{"FieldName":"ReferringPhysicianName","FieldType":"String","ValueBefore":"","ValueAfter":"","Action":2},{"FieldName":"InsuranceProvider","FieldType":"String","ValueBefore":"","ValueAfter":"","Action":2},{"FieldName":"TreatmentId","FieldType":"String","ValueBefore":"","ValueAfter":"","Action":2},{"FieldName":"RowVersion[6]","FieldType":"Byte","ValueBefore":"10","ValueAfter":"115","Action":2},{"FieldName":"OrderStatusType.Id","FieldType":"Int32","ValueBefore":"8","ValueAfter":"10","Action":2},{"FieldName":"OrderStatusType.Description","FieldType":"String","ValueBefore":"Delivered","ValueAfter":"Failed Logistics","Action":2},{"FieldName":"OrderStatusType.IsSelectable","FieldType":"Boolean","ValueBefore":"False","ValueAfter":"True","Action":2}]'
SELECT #JSONData = JSON_MODIFY(#JSONData, '$',
JSON_QUERY(
(
SELECT *
FROM OPENJSON(#JSONData, '$') WITH (
FieldName nvarchar(1000) '$.FieldName',
FieldType nvarchar(1000) '$.FieldType',
ValueBefore nvarchar(1000) '$.ValueBefore',
ValueAfter nvarchar(1000) '$.ValueAfter',
Action int '$.Action'
)
WHERE Action <> 2 AND ValueBefore <> ValueAfter
FOR JSON PATH
)
)
)
Error:
Msg 13619, Level 16, State 1, Line 4
Unsupported JSON path found in argument 2 of JSON_MODIFY.
The expected output I'm looking for is:
[{"FieldName":"OrderStatusTypeId","FieldType":"Int32","ValueBefore":"8","ValueAfter":"10","Action":2},{"FieldName":"RowVersion[6]","FieldType":"Byte","ValueBefore":"10","ValueAfter":"115","Action":2},{"FieldName":"OrderStatusType.Id","FieldType":"Int32","ValueBefore":"8","ValueAfter":"10","Action":2},{"FieldName":"OrderStatusType.Description","FieldType":"String","ValueBefore":"Delivered","ValueAfter":"Failed Logistics","Action":2},{"FieldName":"OrderStatusType.IsSelectable","FieldType":"Boolean","ValueBefore":"False","ValueAfter":"True","Action":2}]
How can I work out the correct JSON Path value, all the examples I seem to find online don't have an array as the root element of the JSON string.
Note, the order of the elements isn't important.
You don't have to use JSON_MODIFY here. You can just select the data you want as a table, filter it, then re-encode it as JSON.
DECLARE #JSONData AS NVARCHAR(4000)
SET #JSONData = N'[{"FieldName":"OrderStatusTypeId","FieldType":"Int32","ValueBefore":"8","ValueAfter":"10","Action":2},{"FieldName":"PatientReferenceNumber","FieldType":"String","ValueBefore":"","ValueAfter":"","Action":2},{"FieldName":"PoNumber","FieldType":"String","ValueBefore":"","ValueAfter":"","Action":2},{"FieldName":"ReferringPhysicianName","FieldType":"String","ValueBefore":"","ValueAfter":"","Action":2},{"FieldName":"InsuranceProvider","FieldType":"String","ValueBefore":"","ValueAfter":"","Action":2},{"FieldName":"TreatmentId","FieldType":"String","ValueBefore":"","ValueAfter":"","Action":2},{"FieldName":"RowVersion[6]","FieldType":"Byte","ValueBefore":"10","ValueAfter":"115","Action":2},{"FieldName":"OrderStatusType.Id","FieldType":"Int32","ValueBefore":"8","ValueAfter":"10","Action":2},{"FieldName":"OrderStatusType.Description","FieldType":"String","ValueBefore":"Delivered","ValueAfter":"Failed Logistics","Action":2},{"FieldName":"OrderStatusType.IsSelectable","FieldType":"Boolean","ValueBefore":"False","ValueAfter":"True","Action":2}]'
set #JSONData =
(
SELECT *
FROM OPENJSON(#JSONData, '$') WITH (
FieldName nvarchar(1000) '$.FieldName',
FieldType nvarchar(1000) '$.FieldType',
ValueBefore nvarchar(1000) '$.ValueBefore',
ValueAfter nvarchar(1000) '$.ValueAfter',
Action int '$.Action'
)
WHERE not (Action = 2 and ValueBefore = ValueAfter)
FOR JSON PATH
)
and the JSON is
[
{
"FieldName": "OrderStatusTypeId",
"FieldType": "Int32",
"ValueBefore": "8",
"ValueAfter": "10",
"Action": 2
},
{
"FieldName": "RowVersion[6]",
"FieldType": "Byte",
"ValueBefore": "10",
"ValueAfter": "115",
"Action": 2
},
{
"FieldName": "OrderStatusType.Id",
"FieldType": "Int32",
"ValueBefore": "8",
"ValueAfter": "10",
"Action": 2
},
{
"FieldName": "OrderStatusType.Description",
"FieldType": "String",
"ValueBefore": "Delivered",
"ValueAfter": "Failed Logistics",
"Action": 2
},
{
"FieldName": "OrderStatusType.IsSelectable",
"FieldType": "Boolean",
"ValueBefore": "False",
"ValueAfter": "True",
"Action": 2
}
]

How to use JSON_VALUE in where in clause (SQL Server)

: am trying to use part of a JSON to use as a filter for a where in clause as follows:
declare #json nvarchar(max) =
'[{
"brand_name": {
"key": "Brand Name",
"value": "''alpha'',''omega''"
}
}]';
select *
from someTable
where column in (select json_value(#json, '$[0].brand_name.value'));
How do I convert the value into a where-in argument?
Like this:
declare #json nvarchar(max) =
'[{
"brand_name": {
"key": "Brand Name",
"value": ["alpha","omega"]
}
}]';
select value from openjson(#json, '$[0].brand_name.value')

How output a nested array in json using SQL query?

What I'm trying to do is create a stored procedure in SQL using the below table and output an expected json like in the below.
A multiple object inside an array of an object of json
[
{
"Category": "Popularity",
"ItemData":[
{
"ItemId": "1",
"ItemName": "CocaCola",
"Image1": "https://www.foodbusinessnews.net/ext/resources/2019/2/CocaColaFlavors_Lead.jpg?1550182643",
"FavId": "1",
"ItemDesc": "gg",
"Category": "My Favorite"
},
{
"ItemId": "1",
"ItemName": "CocaCola",
"Image1": "https://www.foodbusinessnews.net/ext/resources/2019/2/CocaColaFlavors_Lead.jpg?1550182643",
"FavId": "1",
"ItemDesc": "gg",
"Category": "My Favorite"
},
],
"Category": "Family Style",
"ItemData":[
{
"ItemId": "1",
"ItemName": "Buritos",
"Image1": "https://www.foodbusinessnews.net/ext/resources/2019/2/CocaColaFlavors_Lead.jpg?1550182643",
"FavId": "1",
"ItemDesc": "gg",
"Category": "My Favorite"
},
{
"ItemId": "1",
"ItemName": "Mountain Dew",
"Image1": "https://www.foodbusinessnews.net/ext/resources/2019/2/CocaColaFlavors_Lead.jpg?1550182643",
"FavId": "1",
"ItemDesc": "gg",
"Category": "My Favorite"
},
],
}
]
FoodAppItem table
FoodAppCategory table
FoodAppLinker table
Since there are a lot of category in 1 item, I create a linker table to input multiple category in 1 item instead of inserting it into the main Item Table
FoodAppItem.ItemId = FoodAppLinker.ItemId
FoodApplinker.CategoryId = FoodAppLinker.CategoryId
This is my main problem => Help me guys to group the item into category and get the item in each category, I'm okay if the json output is different as long as this condition meet. Thank you
By the way I'm using api to convert the SQL output to json
This is what I have done so far
ALTER PROCEDURE [dbo].[procFoodAppSelectFoodCategory]
#CategoryId int
AS
BEGIN
DECLARE #Count INT
DECLARE #RetCode INT
DECLARE #RetMsg VARCHAR(100)
SELECT #RetCode = 1, #RetMsg = ''
SET #Count = (SELECT COUNT(*) FROM FoodAppCategory
WHERE FoodAppCategory.CategoryId = #CategoryId)
IF #Count > 0
SELECT
FoodAppItem.ItemId, FoodAppItem.ItemName, FoodAppItem.Image1,
FoodAppCategory.Category
FROM
FoodAppItem
INNER JOIN
FoodAppLinker ON FoodAppItem.ItemId = FoodAppLinker.ItemId
INNER JOIN
FoodAppCategory ON FoodAppLinker.CategoryId = FoodAppCategory.CategoryId
WHERE
FoodAppCategory.CategoryId = #CategoryId
ELSE
SET #RetCode = 3
SET #RetMsg = 'Empty' + CHAR(13) + CHAR(10)
IF #RetCode = 3
BEGIN
SELECT TOP 1 #RetCode RetCode, #RetMsg RetMsg
RETURN
END
END
it display the items depends on the category id that I input, what I need is it automatically sort the item base on the category without inputting an ID

How to call Json in sql query

I want to display the parameter ST and NextTime from table #json. The parameters id and Timestamp appear normally. I try the following but does not show any effect.Any possible answers?
My Json
{
"PCol": [{
"Id": 15,
"TimeStamp": "2018-02-1",
"Val": {
"States": [{
"Numbers": {
"Number": [5, 8]
},
"CS": {
"ST": "25"
},
"Changes": [{
"NextTime": 1
}]
}]
}
}]
}
My Sql Query
SELECT * FROM OPENJSON((select * from #json),N'$.PCol')
WITH (
[Id] INT N'$.Id ',
[TimeStamp] NVARCHAR(MAX) N'$.TimeStamp',
**[ST] INT N'$.Val.States.CS.ST'**
)
Thanks
Not going to lie, my OPENJSON knowledge is poor (so this might be able to be more succinct), however, this works:
DECLARE #JSON nvarchar(MAX) =
N' {
"PCol": [{
"Id": 15,
"TimeStamp": "2018-02-1",
"Val": {
"States": [{
"Numbers": {
"Number": [5, 8]
},
"CS": {
"ST": "25"
}
}]
}
}]
} ';
SELECT P.Id,
P.TimeStamp,
V.ST
FROM OPENJSON(#JSON,N'$.PCol') WITH ([Id] INT N'$.Id ',
[TimeStamp] NVARCHAR(MAX) N'$.TimeStamp',
[Vals] nvarchar(MAX) N'$.Val' AS JSON) P
CROSS APPLY OPENJSON(P.Vals,N'$.States') WITH (ST int N'$.CS.ST') V
For the latest JSON, this works:
SELECT P.Id,
P.TimeStamp,
V.ST,
C.NextTime
FROM OPENJSON(#JSON,N'$.PCol') WITH ([Id] INT N'$.Id ',
[TimeStamp] NVARCHAR(MAX) N'$.TimeStamp',
[Vals] nvarchar(MAX) N'$.Val' AS JSON) P
CROSS APPLY OPENJSON(P.Vals,N'$.States') WITH (ST int N'$.CS.ST',
[Changes] nvarchar(MAX) N'$.Changes' AS JSON) V
CROSS APPLY OPENJSON(V.[Changes]) WITH (NextTime int '$.NextTime') C