Get keys into JSON column in SQL Server 2017 - sql

I have this Json in a column of type NVARCHAR(MAX) in SQL Server 2017:
{
"coreTimes": {
"TMP_CLINICAL_TIMES_ANESTHESIOLOGY_OUT_DATETIME": {
"value": 1
},
"TMP_CLINICAL_TIMES_ANESTHESIOLOGY_IN_DATETIME": {
"value": 2
},
"TMP_CLINICAL_TIMES_SURGICAL_OUT_DATETIME": {
"value": 3
},
"TMP_CLINICAL_TIMES_ROOM_IN_DATETIME": {
"value": 4
},
"TMP_CLINICAL_TIMES_ROOM_OUT_DATETIME": {
"value": null
},
"TMP_CLINICAL_TIMES_BLOCK_OUT_DATETIME": {
"value": null
},
"TMP_CLINICAL_TIMES_BLOCK_IN_DATETIME": {
"value": null
},
"TMP_CLINICAL_TIMES_SURGICAL_IN_DATETIME": {
"value": null
}
}
}
I need this result:
Column
{"value":1}
{"value":2}
{"value":3}
{"value":4}
{"value":null}
{"value":null}
{"value":null}
What SQL Server 2017 function can I use to get this result if json properties can change dynamically (the key 'coreTimes' is fixed)?
In Oracle I have used:
SELECT res.*
FROM sopinterventionsaux ,
JSON_TABLE ( operating_times, '$.coreTimes.*'
COLUMNS (
value VARCHAR2 ( 2000 ) FORMAT JSON PATH '$'
)
) res
In PostgreSQL:
select value from table, jsonb_each(column-> 'coreTimes')
And in SQL Server?

If I understand you correctly, you need to use OPENJSON() with default schema to parse the input JSON. In this case OPENJSON() returns a table with columns key, value and type:
Table:
DECLARE #json nvarchar(max) = N'{
"coreTimes": {
"TMP_CLINICAL_TIMES_ANESTHESIOLOGY_OUT_DATETIME": {
"value": 1
},
"TMP_CLINICAL_TIMES_ANESTHESIOLOGY_IN_DATETIME": {
"value": 2
},
"TMP_CLINICAL_TIMES_SURGICAL_OUT_DATETIME": {
"value": 3
},
"TMP_CLINICAL_TIMES_ROOM_IN_DATETIME": {
"value": 4
},
"TMP_CLINICAL_TIMES_ROOM_OUT_DATETIME": {
"value": null
},
"TMP_CLINICAL_TIMES_BLOCK_OUT_DATETIME": {
"value": null
},
"TMP_CLINICAL_TIMES_BLOCK_IN_DATETIME": {
"value": null
},
"TMP_CLINICAL_TIMES_SURGICAL_IN_DATETIME": {
"value": null
}
}
}'
CREATE TABLE Data (JsonData nvarchar(max))
INSERT INTO Data (JsonData) VALUES (#json)
Statement:
SELECT j.[value]
FROM Data d
CROSS APPLY OPENJSON(d.JsonData, '$.coreTimes') j
Result:
---------------
value
---------------
{"value": 1}
{"value": 2}
{"value": 3}
{"value": 4}
{"value": null}
{"value": null}
{"value": null}
{"value": null}
If you want to get the exact values for the value keys, you need to use OPENJSON() with explicit schema (with columns definitions) and additional APPLY operator.
Statement:
SELECT j2.[value]
FROM Data d
CROSS APPLY OPENJSON(d.JsonData, '$.coreTimes') j1
CROSS APPLY OPENJSON(j1.[value]) WITH ([value] int '$.value') j2
Result:
-----
value
-----
1
2
3
4
NULL
NULL
NULL
NULL

Please try following:
declare #j nvarchar(max) = '{
"coreTimes": {
"TMP_CLINICAL_TIMES_ANESTHESIOLOGY_OUT_DATETIME": {
"value": 1
},
"TMP_CLINICAL_TIMES_ANESTHESIOLOGY_IN_DATETIME": {
"value": 2
},
"TMP_CLINICAL_TIMES_SURGICAL_OUT_DATETIME": {
"value": 3
},
"TMP_CLINICAL_TIMES_ROOM_IN_DATETIME": {
"value": 4
},
"TMP_CLINICAL_TIMES_ROOM_OUT_DATETIME": {
"value": null
},
"TMP_CLINICAL_TIMES_BLOCK_OUT_DATETIME": {
"value": null
},
"TMP_CLINICAL_TIMES_BLOCK_IN_DATETIME": {
"value": null
},
"TMP_CLINICAL_TIMES_SURGICAL_IN_DATETIME": {
"value": null
}
}
}'
select L1.[Value] from OPENJSON (#j, '$.coreTimes') AS L1

Related

Parse Google API JSON file to rows and columns with OPENJSON in T-SQL

So I am trying to create a query than can handle a json file that we get with a data factory web request from the Google Analytics API 4 and store the result in an Azure sql table. The following query is the closest I got.
The dimension and metric headers seems to be column names and the values in the rows part should be the rows.
DECLARE #jsonexample NVARCHAR(MAX) =
N'{
"dimensionHeaders": [
{
"name": "date"
},
{
"name": "country"
}
],
"metricHeaders": [
{
"name": "totalUsers",
"type": "TYPE_INTEGER"
}
],
"rows": [
{
"dimensionValues": [
{
"value": "20230207"
},
{
"value": "Netherlands"
}
],
"metricValues": [
{
"value": "3"
}
]
},
{
"dimensionValues": [
{
"value": "20230208"
},
{
"value": "Netherlands"
}
],
"metricValues": [
{
"value": "2"
}
]
},
{
"dimensionValues": [
{
"value": "20230208"
},
{
"value": "United States"
}
],
"metricValues": [
{
"value": "1"
}
]
}
]
}'
DECLARE #jsonexample2 NVARCHAR(MAX) = (SELECT [value] FROM OPENJSON(#jsonexample) where [key]= 'rows' )
SELECT *
from OPENJSON(#jsonexample2)
This blog seemed to have a good explanation but I still not got it working.
https://levelup.gitconnected.com/how-to-easily-parse-and-transform-json-in-sql-server-c0b091a964de
You can shred it down to something like this:
DECLARE #jsonexample NVARCHAR(MAX) =
N'{
"dimensionHeaders": [
{
"name": "date"
},
{
"name": "country"
}
],
"metricHeaders": [
{
"name": "totalUsers",
"type": "TYPE_INTEGER"
}
],
"rows": [
{
"dimensionValues": [
{
"value": "20230207"
},
{
"value": "Netherlands"
}
],
"metricValues": [
{
"value": "3"
}
]
},
{
"dimensionValues": [
{
"value": "20230208"
},
{
"value": "Netherlands"
}
],
"metricValues": [
{
"value": "2"
}
]
},
{
"dimensionValues": [
{
"value": "20230208"
},
{
"value": "United States"
}
],
"metricValues": [
{
"value": "1"
}
]
}
]
}'
;with cols as (
select cast([key] as int) AS k, JSON_VALUE(value, '$.name') AS v
from openjson(#jsonexample, '$.dimensionHeaders') x
)
, metrics as (
select cast([key] as int) AS k, JSON_VALUE(value, '$.name') AS v
from openjson(#jsonexample, '$.metricHeaders') x
)
select CAST(x.[key] AS INT) AS id, c.v AS dimName, JSON_VALUE(dim.value, '$.value') AS dimValue
, m.v AS metName, JSON_VALUE(metr.value, '$.value') AS metValue
from openjson(#jsonexample, '$.rows') x
cross apply openjson(x.value, '$.dimensionValues') dim
cross apply openjson(x.value, '$.metricValues') metr
inner join cols c
ON c.k = dim.[key]
inner join metrics m
ON m.k = metr.[key]
Then you can probably figure out the rest.
Here is a bit code that will dynamically parse the metrics and dimension for Google Analytics. It should give you a good starting point :)
SELECT TOP 1 #json = JSON_QUERY(RawJson, '$.reports[0].columnHeader')
FROM TableName
SET #WithClause =
(
SELECT STRING_AGG(Line, ',')
FROM
(
SELECT REPLACE(r.value, 'ga:', '')+' '+CASE
WHEN r.value = 'ga:DATE' THEN 'DATE'
ELSE 'NVARCHAR(255)'
END+' '+'''$.dimensions['+r.[key]+']''' AS Line
FROM OPENJSON(#json, '$.dimensions') AS r
UNION ALL
SELECT REPLACE(JSON_VALUE(r.value, '$.name'), 'ga:', '')+' '+CASE
WHEN JSON_VALUE(r.value, '$.type') = 'TIME' THEN 'FLOAT'
WHEN JSON_VALUE(r.value, '$.type') = 'CURRENCY' THEN 'DECIMAL(9,2)'
ELSE JSON_VALUE(r.value, '$.type')
END+' '+'''$.metrics[0].values['+r.[key]+']'''
FROM OPENJSON(#json, '$.metricHeader.metricHeaderEntries') AS r
) AS a
);
SET #Query = '
SELECT d.*
INTO #temp_table
FROM TableNAme AS cm
CROSS APPLY OPENJSON(RawJson, ''$.reports[0].data.rows'') WITH ( '+#WithClause+ ') AS d';
--PRINT #Query;
EXECUTE (#Query);

How to extract a value in a JSON table on BigQuery?

I have a JSON table which has over 30.000 rows. There are different rows like this:
JSON_columns
------------
{
"level": 20,
"nickname": "ABCDE",
"mission_name": "take_out_the_trash",
"mission_day": "150",
"duration": "0",
"properties": []
}
{
"nickname": "KLMNP",
"mission_name": "recycle",
"mission_day": "180",
"properties": [{
"key": "bottle",
"value": {
"string_value": "blue_bottle"
}
}, {
"key": "bottleRecycle",
"value": {
"string_value": "true"
}
}, {
"key": "price",
"value": {
"float_value": 21.99
}
}, {
"key": "cost",
"value": {
"float_value": 15.39
}
}]
}
I want to take the sum of costs the table. But firtsly, I want to extract the cost from the table.
I tried the code below. It returns null:
SELECT JSON_VALUE('$.properties[3].value.float_value') AS profit
FROM `missions.missions_study`
WHERE mission_name = "recycle"
My question is, how can I extract the cost values right, and sum them?
Common way to extract cost from your json is like below.
WITH sample_table AS (
SELECT '{"level":20,"nickname":"ABCDE","mission_name":"take_out_the_trash","mission_day":"150","duration":"0","properties":[]}' json
UNION ALL
SELECT '{"nickname":"KLMNP","mission_name":"recycle","mission_day":"180","properties":[{"key":"bottle","value":{"string_value":"blue_bottle"}},{"key":"bottleRecycle","value":{"string_value":"true"}},{"key":"price","value":{"float_value":21.99}},{"key":"cost","value":{"float_value":15.39}}]}' json
)
SELECT SUM(cost) AS total FROM (
SELECT CAST(JSON_VALUE(prop, '$.value.float_value') AS FLOAT64) AS cost
FROM sample_table, UNNEST(JSON_QUERY_ARRAY(json, '$.properties')) prop
WHERE JSON_VALUE(json, '$.mission_name') = 'recycle'
AND JSON_VALUE(prop, '$.key') = 'cost'
);

BigQuery concat nested array json

I have data that looks like
{
"Attributes": [
{
"values": [
{
"value": "20003"
},
{
"value": "30075"
},
{
"value": "40060"
}
],
"name": "price"
}
],
"attr2" : "val"
}
The output I want is concat all the values in the nested json array
price, "20003, 30075, 40060"
I tried some queries but failed to get the correct output.
You can use JSON_EXTRACT_ARRAY and ARRAY_TO_STRING:
WITH test_json AS (
SELECT
'''{
"Attributes": [
{
"values": [
{
"value": "20003"
},
{
"value": "30075"
},
{
"value": "40060"
}
],
"name": "price"
}
],
"attr2" : "val"
}''' AS json_string
),
values_concatenated AS (
SELECT ARRAY_TO_STRING(
ARRAY(
SELECT JSON_VALUE(json_values, '$.value')
FROM UNNEST((SELECT JSON_EXTRACT_ARRAY(json_string, '$.Attributes[0].values') AS json_values FROM test_json)) as json_values
),
', '
) as values
)
SELECT
(select json_value(json_string, '$.Attributes[0].name') from test_json),
(select values from values_concatenated)

Advice on using OPENJSON to parse a nested array

I am hoping somebody can help point me in the right direction as Iā€™m trying to parse a json file into sql using OPENJSON. I have a structure which looks like this:
DECLARE #json AS NVARCHAR(MAX) = '
[{
"id": "78",
"Version": {
"Value": "12"
},
"Names": [{
"NameId": {
"Value": "8516365"
},
"id": "328787",
"NameLinkType": {
"Value": "A"
"CommsChains": {
"Value": [[{
"com_primary": {
"Value": "Y"
},
"com_recd": {
"Value": "2020-07-07 00:00:00.000"
},
"com_ack": {
"Value": "2020-07-09 00:00:00.000"
},
}
]]
), },
},
],
}
]'
I am able to parse the majority of the JSON correctly, so for each ID I can return values such as Version or NameId. However, I am unable to return any dates in respect of com_recd or com_ack, which sit under CommsChains [Object] ā€“ Value [Array] ā€“ [0] [Array]
It looks like there are some syntactic errors in your JSON. After having them fixed, I was able to try and find the JSON paths to the date expressions to the date values. This is the SQL:
DECLARE #json AS NVARCHAR(MAX) = '
[{
"id": "78",
"Version": {
"Value": "12"
},
"Names": [{
"NameId": {
"Value": "8516365"
},
"id": "328787",
"NameLinkType": {
"Value": "A",
"CommsChains": {
"Value": [[{
"com_primary": {
"Value": "Y"
},
"com_recd": {
"Value": "2020-07-07 00:00:00.000"
},
"com_ack": {
"Value": "2020-07-09 00:00:00.000"
}
}
]]
}
}
}
]
}
]'
select * from openjson(#json, '$[0].Version');--Value 12 1
select * from openjson(#json, '$[0].Names');
select * from openjson(#json, '$[0].Names[0]');
select * from openjson(#json, '$[0].Names[0].NameLinkType');
select * from openjson(#json, '$[0].Names[0].NameLinkType.CommsChains');
select * from openjson(#json, '$[0].Names[0].NameLinkType.CommsChains.Value');
select * from openjson(#json, '$[0].Names[0].NameLinkType.CommsChains.Value[0]');
select * from openjson(#json, '$[0].Names[0].NameLinkType.CommsChains.Value[0][0]');
select * from openjson(#json, '$[0].Names[0].NameLinkType.CommsChains.Value[0][0].com_recd'); --selecting path for com_recd
select * from openjson(#json, '$[0].Names[0].NameLinkType.CommsChains.Value[0][0].com_ack'); --selecting path for com_ack
Herein I show the selects to the different parts of your JSON. The arrays'content are always referenced as [0] as its always the first index to select here.
For more information on JSON paths on the SQL server look here

How to filter Cosmos DB data based on value of an element in an array of values Using SQL API

I have a cosmosDB collection with below Data in it.
I have to find out the data only for EVENT named ABC and its value using SQL query.
[
{
"ID": "01XXXXX",
"EVENTS": [
{
"Name": "ABC",
"Value": 0
},
{
"Name": "XYZ",
"Value": 4
},
{
"Name": "PQR",
"Value": 5
}
]
},
{
"ID": "02XXXXX",
"EVENTS": [
{
"Name": "ABC",
"Value": 1
},
{
"Name": "XYZ",
"Value": 2
},
{
"Name": "PQR",
"Value": 3
}
]
}
]
I have tried the below code but it is not working since EVENT is an array.
SELECT * FROM c where c.EVENTS.Name = 'ABC'
Is there any way to find filter out the data only with Event Name as ABC using SQL?
Try using join
SELECT c FROM c
join l in c.EVENTS
where l.Name = 'ABC'