I have a table that stores 1 json object per row, I want to call OPENJSON on the json object stored in each row and union together all of the results. I don't know the number of rows I will have ahead of time.
Here is some example data to reference
DROP TABLE #tmp_json_tbl
DECLARE #json1 NVARCHAR(2048) = N'{
"members": [
{
"name": "bob",
"status": "subscribed"
},
{
"name": "larry",
"status": "unsubscribed"
}
]
}';
SELECT #json1 as json_obj,1 as jid into #tmp_json_tbl
INSERT into #tmp_json_tbl
VALUES ( N'{
"members": [
{
"name": "bob",
"status": "subscribed"
},
{
"name": "larry",
"status": "unsubscribed"
}
]
}',2 );
SELECT * from #tmp_json_tbl
--how can i recursively union together results for all values of jid?
-- I could use a cursor but I would rather figure out a way to do it using a recursive cte
SELECT * FROM OpenJson((SELECT json_obj from #tmp_json_tbl where jid=1), '$.members')
WITH (
name VARCHAR(80) '$.name',
mstatus varchar(100) '$.status'
)```
This is what I wanted
SELECT name, m_status
FROM #tmp_json
CROSS APPLY OPENJSON(j, '$.members')
WITH (
name VARCHAR(80) '$.name',
m_status varchar(100) '$.status'
)
Found my answer here: How to use OPENJSON on multiple rows
Related
I have some difficulty in writing a query to query data from nested json in Cosmos db.
Sample json -
{
"id": xyz
"items": [
{
"arr_id": 1,
"randomval": "abc"
},
{
"arr_id": 2,
"randomval": "mno"
},
{
"arr_id": 1,
"randomval": "xyz"
}
]
}
Lets say in above case, if i want to get all jsons data with arr_id = 1.
Expected Result -
{
"id": xyz
"items": [
{
"arr_id": 1,
"randomval": "abc"
},
{
"arr_id": 1,
"randomval": "xyz"
}
]
}
If i write a query like below, it still gives me entire json.
Select * from c where ARRAY_CONTAINS(c.items, {"arr_id": 1},true)
I want it to filter it items level too. I guess it just filters at header level and provides entire json where even a single arr_id matches.
You can use either
SELECT c.id, ARRAY(SELECT VALUE i FROM i in c.items where i.arr_id = 1) as items
FROM c
WHERE EXISTS(SELECT VALUE i FROM i in c.items where i.arr_id = 1)
or
SELECT c.id, ARRAY(SELECT VALUE i FROM i in c.items where i.arr_id = 1) as items
FROM c
depending on whether you expect an empty array if no arrayItem with arr_id=1 exists or you wnat to filter out those records compeletely.
Also see this link for a good overview of query options across arrays - https://devblogs.microsoft.com/cosmosdb/understanding-how-to-query-arrays-in-azure-cosmos-db/
I'm trying to understand the documentation about JOIN in Cosmos DB SQL.
In the sample JSON, each family object has a children property, like this:
First family object:
"id": "AndersenFamily",
"lastName": "Andersen",
"children": [
{
"firstName": "Henriette Thaulow",
"grade": 5
}
],
Second family object:
"id": "WakefieldFamily",
"children": [
{
"givenName": "Jesse"
}
],
Then, this JOIN operation is shown:
SELECT f.id
FROM Families f
JOIN f.children
The obvious result is the identifier of each family object.
[
{
"id": "AndersenFamily"
},
{
"id": "WakefieldFamily"
}
]
If the "JOIN" is removed, the result is exactly the same. Even I wanted to project the children, I could just use SELECT f.id, f.children and there would be no reason to join f.children.
The only difference I observe is if a family object didn't have a children property. Then the joining on f.children would exclude the family object from the results.
So what is the point of a JOIN in Cosmos DB SQL without combining it with IN? Is there any real use cases for it?
I'm trying to parse a json object like this one:
{
"sites": [
{
"code": "code",
"siteName": "site name",
"country": "country",
"arrayToClob": [
{
"field1": "field 1",
"field2": "field 2"
}
]
}
]
}
and I want to store the value of "arrayToClob" element into a Clob column of my DB and for that I'm trying to get the value of that element as a whole. This is what I tried:
APEX_JSON.parse(MY_JSON);
l_count := APEX_JSON.get_count('sites');
FOR i IN 1 .. l_count LOOP
l_code := APEX_JSON.get_varchar2('sites[%d].code', i);
l_siteName := APEX_JSON.get_varchar2('sites[%d].siteName', i);
l_country := APEX_JSON.get_varchar2('sites[%d].country', i);
l_value := APEX_JSON.get_array('sites[%d].arrayToClob', i);
END LOOP;
where l_value is type json_array_t... but of course is not working. I've tried also with varchar2 type and I've check other options here https://docs.oracle.com/cd/E59726_01/doc.50/e39149/apex_json.htm#AEAPI29655
I don't know how to approach it, I don't know if it's even possible what I want... any tips will be welcome.
Thanks in advance
You mean that the value for "field1" is a CLOB value in your actual data ? If that is not the case and it is just a varchar it's possible to use JSON_TABLE to get what you want in a plain SQL statement. Note that APEX_JSON isn't very performant.
with json_tab AS
(
SELECT
'{
"sites": [
{
"code": "code",
"siteName": "site name",
"country": "country",
"arrayToClob": [
{
"field1": "field 1",
"field2": "field 2"
}
]
}
]
}' as data FROM DUAL
)
SELECT jt.code, jt.field1, jt.field2
FROM json_tab t,
JSON_TABLE(
data,
'$.sites[*]'
columns (
code VARCHAR2(100) PATH '$.code',
NESTED PATH '$.arrayToClob[*]'
columns (
field1 VARCHAR2(32000) PATH '$.field1',
field2 VARCHAR2(32000) PATH '$.field2'
)
)
) jt;
JSON_TABLE does not support CLOB datatype as column - so if it really is a CLOB it won't work.
how to get the value from a specific attribute on the basis of value check of another attribute value in oracle 12c. Below is the JSON
{
"Operational_Cost21":[
{
"Input1":"20000",
"Operational_cost23":"Diesel"
},
{
"Input1":"5000",
"Operational_cost23":"Maintenance"
},
{
"Input1":"20000",
"Operational_cost23":"Other Variable Cost"
},
{
"Input1":"100000",
"Operational_cost23":"Driver Salary"
}
]
}
I want to get the value of input value where operational_cost23 = 'Driver Salary'
expected Value = 100000
You should first add this constraint into your table.CONSTRAINT ensure_json2 CHECK (SAMP IS JSON). Then you can use JSON_TABLE function.
Documentation
DROP TABLE TESTTABLE CASCADE CONSTRAINTS ;
CREATE TABLE TESTTABLE
(
SAMP CLOB
CONSTRAINT ensure_json2 CHECK (SAMP IS JSON));
INSERT INTO TESTTABLE
VALUES (
'{ "Operational_Cost21": [
{
"Input1": "20000",
"Operational_cost23": "Diesel"
},
{
"Input1": "5000",
"Operational_cost23": "Maintenance"
},
{
"Input1": "20000",
"Operational_cost23": "Other Variable Cost"
},
{
"Input1": "100000",
"Operational_cost23": "Driver Salary"
}
]
}');
SELECT J.Input1,J.Operational_cost23
FROM TESTTABLE,
JSON_TABLE(SAMP,'$.Operational_Cost21[*]' COLUMNS
Input1 VARCHAR2(20) PATH '$.Input1',
Operational_cost23 VARCHAR2(20) PATH '$.Operational_cost23'
) J
where operational_cost23 = 'Driver Salary'
This is a follow up to question 56126817
My current query
SELECT c.EventType.EndDeviceEventDetail FROM c
WHERE c.EventType.EndDeviceEventType.eventOrAction = '93'
AND c.EventType.EndDeviceEventType.subdomain = '137'
AND c.EventType.EndDeviceEventType.domain = '26'
AND c.EventType.EndDeviceEventType.type = '3'
AND ARRAY_CONTAINS(c.EventType.EndDeviceEventDetail,{"name":
"RCDSwitchReleased","value": "true" })
My Query Output
[
{
"EndDeviceEventDetail": [
{
"name": "Spontaneous",
"value": "true"
},
{
"name": "DetectionActive",
"value": "true"
},
{
"name": "RCDSwitchReleased",
"value": "true"
}
]
}
]
Question
How could change my query so that I select only the "value" of the array that contains the "name" "DetectionActive" ?
The idea behind is to filter the query on one array entry and get as output the "value" of another array entry. From reading here, UDF (not the best in this case) and JOIN should be used.
First attempt
SELECT t.value FROM c JOIN t in c.EventType.EndDeviceEventDetail
WHERE c.EventType.EndDeviceEventType.eventOrAction = '93'
AND c.EventType.EndDeviceEventType.subdomain = '137'
AND c.EventType.EndDeviceEventType.domain = '26'
AND c.EventType.EndDeviceEventType.type = '3'
AND ARRAY_CONTAINS(c.EventType.EndDeviceEventDetail,{"name":
"RCDSwitchReleased","value": "true" })
Gets Bad Request (400) error
Your idea and direction is right absolutely, I simplified and tested your sql.
SELECT detail.value FROM c
join detail in c.EventType.EndDeviceEventDetail
WHERE c.EventType.EndDeviceEventType.eventOrAction = '93'
AND ARRAY_CONTAINS(c.EventType.EndDeviceEventDetail,{"name":
"RCDSwitchReleased","value": "true" })
Found the error message as below:
It because that the value is the reserved word in cosmos db sql syntax,please refer to this case:Using reserved word field name in DocumentDB
You could try to modify the sql like:
SELECT detail["value"] FROM c