Transform Json Nested Object Array To Table Row - sql

I have a json like:
[
{
"Id": "1234",
"stockDetail": [
{
"Number": "10022_1",
"Code": "500"
},
{
"Number": "10022_1",
"Code": "600"
}
]
},
{
"Id": "1235",
"stockDetail": [
{
"Number": "10023_1",
"Code": "100"
},
{
"Number": "10023_1",
"Code": "100"
}
]
}
]
How to convert it in sql table like below:
+------+---------+------+
| Id | Number | Code |
+------+---------+------+
| 1234 | 10022_1 | 500 |
| 1234 | 10022_1 | 600 |
| 1235 | 10023_1 | 100 |
| 1235 | 10023_1 | 100 |
+------+---------+------+

If you need to define typed columns you can use OPENJSON with WITH clause:
DECLARE #j nvarchar(max) = N'[
{
"Id": "1234",
"stockDetail": [
{ "Number": "10022_1",
"Code": "500"
},
{ "Number": "10022_1",
"Code": "600"
}
]
},
{
"Id": "1235",
"stockDetail": [
{ "Number": "10023_1",
"Code": "100"
},
{ "Number": "10023_1",
"Code": "100"
}
]
}
]'
select father.Id, child.Number, child.Code
from openjson (#j)
with (
Id int,
stockDetail nvarchar(max) as json
) as father
cross apply openjson (father.stockDetail)
with (
Number nvarchar(100),
Code nvarchar(100)
) as child
Result:

In your case you may try to CROSS APPLY the JSON child node with the parent node:
DECLARE #json nvarchar(max)
SET #json = N'
[
{
"Id": "1234",
"stockDetail": [
{
"Number": "10022_1",
"Code": "500"
},
{
"Number": "10022_1",
"Code": "600"
}
]
},
{
"Id": "1235",
"stockDetail": [
{
"Number": "10023_1",
"Code": "100"
},
{
"Number": "10023_1",
"Code": "100"
}
]
}
]'
SELECT
JSON_Value (i.value, '$.Id') as ID,
JSON_Value (d.value, '$.Number') as [Number],
JSON_Value (d.value, '$.Code') as [Code]
FROM OPENJSON (#json, '$') as i
CROSS APPLY OPENJSON (i.value, '$.stockDetail') as d
Output:
ID Number Code
1234 10022_1 500
1234 10022_1 600
1235 10023_1 100
1235 10023_1 100

Related

SQL to get count in JSON data

i am new to sql language. Could anyone sharing some point or solution for my cases?
i'll show the JSON data below, could it possible return some value in the column how many time appear in my json data. look like the table below:
+--------------------------------+
|column |value |totalCount |
+--------------------------------+
|brand |top-brand| (2) |
|brand |low | (1) |
|type |Bobtail | (1) |
|type |Snowshoe | (2) |
+--------------------------------+
[
{
"id": 1,
"name": "cat",
"type": {
"id": 2,
"name": "Snowshoe",
},
"brand": {
"id": 3,
"name": "top-brand",
}
},
{
"id": 2,
"name": "cat",
"type": {
"id": 2,
"name": "Snowshoe",
},
"brand": {
"id": 2,
"name": "low",
}
},
{
"id": 3,
"name": "cat",
"type": {
"id": 1,
"name": "Bobtail",
},
"brand": {
"id": 3,
"name": "top-brand",
}
}
]

SQL - Json query

I have tables similar to below where it has one to many mapping
DECLARE #T1 TABLE(RootId int, [Name] varchar(50))
DECLARE #T2 TABLE(Id int,RootId int, Category varchar(50))
INSERT INTO #T1
VALUES(1,'Some Name 12121'),(2,'Some Name 343434')
INSERT INTO #T2
VALUES(100,1,'Category 3333'),
(101,1,'Category 2222'),
(102,1,'Category 4444'),
(103,1,'Category 5555'),
(104,2,'Category 1111'),
(105,2,'Category 77777')
I am expecting to write query so it produce json as below format, where it had item and array of sub
[
{
"item": {
"rootId": 1,
"name": "Some Name 12121",
"sub": [
{
"id": 100,
"category": "Category 3333"
},
{
"id": 101,
"category": "Category 2222"
}
]
}
}
]
I have tried below but could not achieve the expected output
SELECT T1.RootId,T1.Name,T2.Id AS [Sub.Id],T2.Category as [Sub.Category]
FROM #T1 T1
INNER JOIN #T2 T2 ON T1.RootId = T2.RootId
FOR JSON PATH, root('item')
Is there a way to query so that it produce expected Json
All you need to do is (trivially) alias your table properly and then use AUTO instead of PATH:
SELECT T1.RootId,T1.Name,sub.Id AS Id,sub.Category as Category
FROM #T1 T1
INNER JOIN #T2 sub ON T1.RootId = sub.RootId
FOR JSON AUTO, ROOT('item');
Which outputs (after applying a format prettifier):
{
"item": [
{
"RootId": 1,
"Name": "Some Name 12121",
"sub": [
{
"Id": 100,
"Category": "Category 3333"
},
{
"Id": 101,
"Category": "Category 2222"
},
{
"Id": 102,
"Category": "Category 4444"
},
{
"Id": 103,
"Category": "Category 5555"
}
]
},
{
"RootId": 2,
"Name": "Some Name 343434",
"sub": [
{
"Id": 104,
"Category": "Category 1111"
},
{
"Id": 105,
"Category": "Category 77777"
}
]
}
]
}

Reading JSON array containing JSON object into rows

Based from this answer I found one problem. JSON object is return as NULL.
Suppose that I have a JSON like this:
{
"array_in_json": [
{ "number": 1, "character": "A", "some_object": { "code": 65 } },
{ "number": 2, "character": "B", "some_object": { "code": 66 } },
{ "number": 3, "character": "C", "some_object": { "code": 67 } },
{ "number": 4, "character": "D", "some_object": { "code": 68 } }
]
}
With a query like this:
DECLARE #json NVARCHAR(MAX)
SET #json = '{
"array_in_json": [
{ "number": 1, "character": "A", "some_object": { "code": 65 } },
{ "number": 2, "character": "B", "some_object": { "code": 66 } },
{ "number": 3, "character": "C", "some_object": { "code": 67 } },
{ "number": 4, "character": "D", "some_object": { "code": 68 } }
]
}'
SELECT
a.[number],
a.[character],
a.[some_object]
FROM
OPENJSON(#json) WITH (
Actions NVARCHAR(MAX) '$.array_in_json' AS JSON
) AS i
CROSS APPLY (
SELECT * FROM
OPENJSON(i.Actions) WITH (
[number] NVARCHAR(MAX) '$.number',
[character] NVARCHAR(MAX) '$.character',
[some_object] NVARCHAR(MAX) '$.some_object'
)
) a
This's the result:
number | character | some_object
-------------------------------------------------
1 | 'A' | NULL
2 | 'B' | NULL
3 | 'C' | NULL
4 | 'D' | NULL
I want to know is there a way to get a result like this? (Return JSON as escaped string instead of NULL)
number | character | some_object
-------------------------------------------------
1 | 'A' | '{ "code": 65 }'
2 | 'B' | '{ "code": 66 }'
3 | 'C' | '{ "code": 67 }'
4 | 'D' | '{ "code": 68 }'
You need to use AS JSON option in your schema definition to specify that the $.some_object property contains an inner JSON object:
SELECT
a.[number],
a.[character],
a.[some_object]
FROM
OPENJSON(#json) WITH (
Actions NVARCHAR(MAX) '$.array_in_json' AS JSON
) AS i
CROSS APPLY (
SELECT * FROM
OPENJSON(i.Actions) WITH (
[number] NVARCHAR(MAX) '$.number',
[character] NVARCHAR(MAX) '$.character',
[some_object] NVARCHAR(MAX) '$.some_object' AS JSON
)
) a

Get keys into JSON column in SQL Server 2017

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

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'