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
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);
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'
);
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)
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
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'