I need all value from JSON array - sql

I have a table in which I have JSON data and the field type is NVARCHAR(4000)
[
{"number":1,"booked":0},
{"number":2,"booked":0},
{"number":3,"booked":0},
{"number":4,"booked":1},
{"number":5,"booked":0},
{"number":6,"booked":0},
{"number":7,"booked":0},
{"number":8,"booked":0}
]
I want to query on this field of array, and want the output that Number of booked is 1 and not booked are 7.
I have used JSON_VALUE(), JSON_QUERY() functions but not getting at the point.
I also want that Number:4 is booked.
I am using SQL Server 2016

Hi if i understand all what your're trying todo, thoses example can respond :
DECLARE #json NVARCHAR(MAX)
SET #json =
N'[
{"number":1,"booked":0},
{"number":2,"booked":0},
{"number":3,"booked":0},
{"number":4,"booked":1},
{"number":5,"booked":0},
{"number":6,"booked":0},
{"number":7,"booked":0},
{"number":8,"booked":0}
]'
SELECT number, booked
FROM OPENJSON(#json)
WITH (number int 'strict $.number', booked int 'strict $.booked')
WHERE booked = 1
In futur propose please provide some data and excepted output and query what your're trying .

[
{"number":1,"booked":0},
{"number":2,"booked":0},
{"number":3,"booked":0},
{"number":4,"booked":1},
{"number":5,"booked":0},
{"number":6,"booked":0},
{"number":7,"booked":0},
{"number":8,"booked":0}
]
Select query:
SELECT
COUNT(JSON_VALUE(jsonInfo,'$.booked'))
OVER(PARTITION BY JSON_VALUE(jsonInfo,'$.booked'))
FROM table
GROUP BY JSON_VALUE(jsonInfo,'$.booked')
ORDER BY JSON_VALUE(jsonInfo,'$.booked')

Related

Pulling GUIDs out of a JSON string in SQL Server

I need to pull some GUIDs out of a json string in SQL Server. An example of what the string might look like is as follows:
{"priorityArea":"a273b556-f0ab-4d7a-97ac-ddb7dab06130","priority":"Ensure best possible provision for pupils with specific behaviour issues","startDatePicker":"10/05/2019","deadlineDatePicker":"18/09/2019","userPicker":"48698,48693","actionWidget-1555338252504":"85e3ad8f-2586-4612-a9e7-e1c9d3f66181,6b66328f-c13f-4d8c-81ec-fccb8c1caa6e","resourceWidget-1557502650616":"98714348-cf7d-4583-89d5-c7d61cafea72","sdpGrade-1555338253145":"4"}
The GUID(s) I need is the one that comes after 'resourceWidget-[number]'. I would struggle with this even if the json string looked the same everytime, but there are further challenges:
The position of resourceWidget changes in the string depending on front-end behaviour
The unique number that comes after 'resourceWidget-' changes in every string
Sometimes more than one resource GUID is returned in the string, e.g.
resourceWidget-1555338252504":"98714348-cf7d-4583-89d5-c7d61cafea72, 87ea276b-5b7f-4b44-b05e-775e9fd2690c
If anyone is able to help, it would be much appreciated.
Seems like a simple OPENJSON call and a WHERE would work:
DECLARE #JSON nvarchar(MAX) = N'{
"priorityArea": "a273b556-f0ab-4d7a-97ac-ddb7dab06130",
"priority": "Ensure best possible provision for pupils with specific behaviour issues",
"startDatePicker": "10/05/2019",
"deadlineDatePicker": "18/09/2019",
"userPicker": "48698,48693",
"actionWidget-1555338252504": "85e3ad8f-2586-4612-a9e7-e1c9d3f66181,6b66328f-c13f-4d8c-81ec-fccb8c1caa6e",
"resourceWidget-1557502650616": "98714348-cf7d-4583-89d5-c7d61cafea72",
"sdpGrade-1555338253145": "4"
}';
SELECT TRY_CONVERT(uniqueidentifier,[value]) AS resourceWidget
FROM OPENJSON(#JSON)
WHERE [key] LIKE N'resourceWidget-%';
If the JSON can contain a delimited string, add a STRING_SPLIT:
DECLARE #JSON nvarchar(MAX) = N'{
"priorityArea": "a273b556-f0ab-4d7a-97ac-ddb7dab06130",
"priority": "Ensure best possible provision for pupils with specific behaviour issues",
"startDatePicker": "10/05/2019",
"deadlineDatePicker": "18/09/2019",
"userPicker": "48698,48693",
"actionWidget-1555338252504": "85e3ad8f-2586-4612-a9e7-e1c9d3f66181,6b66328f-c13f-4d8c-81ec-fccb8c1caa6e",
"resourceWidget-1555338252504":"98714348-cf7d-4583-89d5-c7d61cafea72, 87ea276b-5b7f-4b44-b05e-775e9fd2690c",
"sdpGrade-1555338253145": "4"
}';
SELECT TRY_CONVERT(uniqueidentifier,TRIM(SS.[value])) AS resourceWidget --TRIM because your example has a leading space
FROM OPENJSON(#JSON) OJ
CROSS APPLY STRING_SPLIT(OJ.[value],',') SS
WHERE OJ.[key] LIKE N'resourceWidget-%';

Dealing with nested JSON in SQL OPENJSON WITH command?

I have JSON value that has some structure to it but I'm struggling to get to the 3rd level. I am using CROSS APPLY OPENJSON to get to the "Lines" data but I need to get the "Code" out of the TaxCode area... It seems to be it's own JSON array maybe?
Any help would be appreciated... This is what I have so far...
DECLARE #JSONText NVarChar(max) = '{
"UID": "845bc256-6027-4a89-8c05-35e4bb8e6aba",
"Number": "00013608",
"Lines": [{
"RowID": 1,
"Total": 20.0,
"TaxCode": "#{UID=f2cc83e5-0f7f-4831-9d88-dbe110e0683a; Code=S15}"
},{
"RowID": 2,
"Total": 55.49,
"TaxCode": "#{UID=a5cc34e5-0fr4-4325-9d67-bdh110e0683a; Code=S17}"
}]
}';
SELECT J.[UID],J.[Number],LI.*
FROM OPENJSON (#JSONText)
WITH (
[UID] nvarchar(512) '$."UID"',
[Number] nvarchar(50) '$."Number"',
[LineItems] NVarChar(max) '$."Lines"' AS JSON
) J
CROSS APPLY OPENJSON (J.[LineItems])
WITH (
[RowID] INT '$."RowID"',
[Total] Decimal(12,2) '$."Total"',
[TaxCode] NVarChar(512) '$."TaxCode"',
[TaxCodeTest] NVarChar(50) '$."TaxCode.Code"'
) LI;
As the TaxCode value being supplied wasn't a "true" JSON object I had to use some SQL to work with it as a string end get the required data. I ended up creating a function to do it using inspiration from this question...
A SQL Query to select a string between two known strings

Adding a prefix to value derived from sql

I have some JSON data, that due to a quirk on the system it's extracted from, posts two values for the same item. Eg:
[
{
"data":{
"ecfa663b-3dd2-4aef-b25c-e43dd6b82enbRA004":"0001-01-01T00:00:00+00:00",
"ecfa663b-3dd2-4aef-b25c-e43dd6b82enbRA013":"0001-01-01T00:00:00+00:00",
"ecfa663b-3dd2-4aef-b25c-e43dd6b82enbMRA013":"2020-09-21T18:15:36.4919022+01:00",
"ecfa663b-3dd2-4aef-b25c-e43dd6b82enbRA010":"2020-09-21T18:12:35.4119042+01:00",
"ecfa663b-3dd2-4aef-b25c-e43dd6b82enbMRA004":"2020-09-21T00:00:00+01:00"
},
"columns":[
{
"name":"Assessment One",
"keySegment":"RA004",
"mandatory":"true"
},
{
"name":"Assessment Two",
"keySegment":"RA013",
"mandatory":"true"
},
{
"name":"Assessment Three",
"keySegment":"RA010",
"mandatory":"false"
}
]
}
]
RA004 and RA013 are correct, but they are classed as mandatory assessments by the software system and so an "M" prefix is added to the individual person's identifier (the longer number).
My (probably not very efficient) code for extracting this JSON into SQL Server is as follows:
BEGIN TRY
SELECT
LEFT(x.[Key],36) AS "ConnectionID",
y.name AS "Assessment", left(x.[Value],19) as "ReviewDate"
INTO [AssessmentToolsStatus]
FROM OPENJSON(#JSON, '$[0].data') AS x
CROSS APPLY
OPENJSON(#JSON, '$[0].columns')
WITH
(
name nvarchar(50) '$.name',
keySegment nvarchar(10) '$.keySegment',
mandatory nvarchar(10) '$.mandatory'
) y
WHERE REPLACE(x.[Key], Left(x.[Key],36),'') = y.keySegment
However, I'm unsure how to account for the "MRA"s. I want something like "if keySegment in 'RA004', 'RA013') then keySegment = 'M' + keySegment", but I don't quite know how in SQL. I don't need the RA004, RA013 entries because the date stamps are meaningless.
Can anyone help?
Thanks
If I understand the question correctly, a possible solution is the below statement (I assume, that RA004 and RA013 are the items from the $.columns JSON array with $.mandatory equal to "true"):
SELECT
LEFT(x.[Key], 36) AS "ConnectionID",
y.name AS "Assessment",
LEFT(x.[Value], 19) AS "ReviewDate"
-- INTO [AssessmentToolsStatus]
FROM OPENJSON(#JSON, '$[0].data') AS x
JOIN OPENJSON(#JSON, '$[0].columns') WITH (
name nvarchar(50) '$.name',
keySegment nvarchar(10) '$.keySegment',
mandatory nvarchar(10) '$.mandatory'
) y ON
STUFF(x.[key], 1, 36, '') =
CONCAT(CASE WHEN y.mandatory = 'true' THEN 'M' ELSE '' END, y.keySegment)
Result:
ConnectionID Assessment ReviewDate
ecfa663b-3dd2-4aef-b25c-e43dd6b82enb Assessment One 2020-09-21T00:00:00
ecfa663b-3dd2-4aef-b25c-e43dd6b82enb Assessment Two 2020-09-21T18:15:36
ecfa663b-3dd2-4aef-b25c-e43dd6b82enb Assessment Three 2020-09-21T18:12:35

Convert a mssql openjson array type value result to a table?

I have a json object in my Microsoft (MS) SQL Server query. This JSON object does have one value, which is an array of strings.
--this variable holds my JSON object with a value of array type.
declare #json nvarchar(max) = N'{
"value": [
"tapiwanashe",
"robert",
"emmerson",
"ruwimbo",
"takudzwa",
"munyaradzi"
]
}'
My goal is to write a SQL query using the supported MS SQL Server JSON functions that produces a table with one column and six rows of the values in the JSON object value array above.
I have tried to run the JSON_QUERY and the OPENJSON functions. However, both of the two functions return an array of strings as the output. I would like to have a result with one column and six rows.
select JSON_QUERY(#json, '$.value')
select [value] from OPENJSON(#json)
The result I am getting is:
value
---------------
[
"tapiwanashe",
"robert",
"emmerson",
"ruwimbo",
"takudzwa",
"munyaradzi"
]
However, the result I am expecting to get looks like this:
value
-----------
tapiwanashe
robert
emmerson
ruwimbo
takudzwa
munyaradzi
The result must preserve the order on which the values appear in the value array.
Like this:
declare #json nvarchar(max) = N'{
"value": [
"tapiwanashe",
"robert",
"emmerson",
"ruwimbo",
"takudzwa",
"munyaradzi"
]
}'
select value
from openjson(#json,'$.value')
order by [key]
outputs
value
----------
tapiwanashe
robert
emmerson
ruwimbo
takudzwa
munyaradzi

Extracting number from the line of text if the number is not present make it null

I have data which has a number which i need to extract the number is typically followed by "sh-" and should return a null if doesnt have any 'sh-' in it.
the sample of data i have is like this :
Tnsf from sh-849116 Act-13383.38 Unam-13383.38 04/12/12
Tnsf from sh-849116 Act() Unam() 04/12/12
System added, to accommodate the fact that the commencement date was not at the beginning of a quarter.Tnsf from sh-849116 Act() Unam() 04/12/12
RECLASSED PAYMENT IN SAP TO CAR WASH MATERIAL CODE. COULDN'T DELETE FORECOURT PAYMENT SINCE IT WAS ALREADY PAID OUT.
AMO CHANGE. SEE FILE. CAS 5.21.10*Tnsf from sh-849116 Act-12451.20 Unam-12451.20 04/12/12*
The output should be:
84916
84916
84916
null
84916
Thanking you in advance
I have edited it
This will get you the number following the sh-:
DECLARE #string VARCHAR(255) = 'Tnsf from sh-849116 Act-13383.38 Unam-13383.38 04/12/12'
SELECT SUBSTRING(#string,CHARINDEX('sh-',#string)+3,CHARINDEX(' ',#string,CHARINDEX('sh-',#string))-CHARINDEX('sh-',#string)-3)
In your query I would add a CASE statement if sh- is not on every row:
SELECT CASE WHEN CHARINDEX('sh-',StringField) > 0
THEN SUBSTRING(StringField,CHARINDEX('sh-',StringField)+3,CHARINDEX(' ',StringField,CHARINDEX('sh-',StringField))-CHARINDEX('sh-',StringField)-3)
END
FROM YourTable
Declare #string nvarchar(250)
select #string='Tnsf from sh-849116 Act-13383.38 Unam-13383.38 04/12/12'
SELECT SUBSTRING(#string,CHARINDEX('sh-',#string)+3,6)