I am using SNOW_FLAKE and trying to query the data stored in the form of multi level array of elements under column name multi_array as example:
multi_array
[
{
"attribute_1": "hello",
"attribute_2": "hello1",
"group_attrbutes": [
{
"grp_attr1": "tst_val",
"grp_attr2": "test_val2"
}
]
}
]
The flatten output would be:
attribute_1 attribute_2 grp_attr1 grp_attr2
hello hello1 tst_val tast_val2
can any one please advise how do i flatten the group_attrbutes array so that it would get in tabular form
SELECT d.json
,f.value:attribute_1 as attribute_1
,f.value:attribute_2 as attribute_2
,g.value:grp_attr1 as grp_attr1
,g.value:grp_attr2 as grp_attr2
FROM (
SELECT parse_json('[
{
"attribute_1": "hello",
"attribute_2": "hello1",
"group_attrbutes": [
{
"grp_attr1": "tst_val",
"grp_attr2": "test_val2"
}
]
}
]') as json
) AS d,
table(flatten(input => d.json)) f,
table(flatten(input => f.value:group_attrbutes)) g
;
gives (with the JSON stripped out):
ATTRIBUTE_1 ATTRIBUTE_2 GRP_ATTR1 GRP_ATTR2
"hello" "hello1" "tst_val" "test_val2"
Related
UPDATE tab s
SET s.DATA = json_transform(DATA, REPLACE '$.dataFilterDefn.columns[1]' = (SELECT JSON_ARRAYAGG(JSON FORMAT JSON RETURNING CLOB)
FROM
(SELECT JSON
FROM
(SELECT j.json || ',' || JSON AS json
FROM tab d
CROSS APPLY JSON_TABLE(d.tab, '$.dataFilterDefn.columns[1]' COLUMNS(json CLOB FORMAT JSON PATH '$')) j
WHERE d.UID = 252))));
The data look like this:
"columns":[
{
"label":"Subcategory",
"aggFn":"NONE",
"datasetId":"ADVENTURE_WORKS",
"fieldName":"SUB_CAT",
"id":"FILTER-1"
}
]
My expectation:
"columns":[
{
"label":"Subcategory",
"aggFn":"NONE",
"datasetId":"ADVENTURE_WORKS",
"fieldName":"SUB_CAT",
"id":"FILTER-1"
},
{
"label":"Subcategory",
"aggFn":"NONE",
"datasetId":"ADVENTURE_WORKS",
"fieldName":"SUB_CAT",
"id":"FILTER-1"
}
]
I want the columns data should duplicate.The columns value will be different.It"ll not be the same. I need to update the column values dynamically..It should not be hardcoded. How can I achieve this in json using Oracle version 19c?
Using json_transform you can append items to an array. Using json_query you can extract the first element of the array.
So you can do something like this:
with rws as (
select '{ "columns":[
{
"label":"Subcategory",
"aggFn":"NONE",
"datasetId":"ADVENTURE_WORKS",
"fieldName":"SUB_CAT",
"id":"ART-DATA-FILTER-1"
}
] }' jdata
from dual
)
select json_transform (
jdata,
append '$.columns' = json_query ( jdata, '$.columns[0]' )
returning varchar2 pretty
)
from rws r;
{
"columns" :
[
{
"label" : "Subcategory",
"aggFn" : "NONE",
"datasetId" : "ADVENTURE_WORKS",
"fieldName" : "SUB_CAT",
"id" : "ART-DATA-FILTER-1"
},
{
"label" : "Subcategory",
"aggFn" : "NONE",
"datasetId" : "ADVENTURE_WORKS",
"fieldName" : "SUB_CAT",
"id" : "ART-DATA-FILTER-1"
}
]
}
Note that json_transform was only added in a recent release update, so ensure your 19c version is fully patched and up-to-date.
Hi I am trying to flatten json with 4 levels of nested arrays. What is the best way to flatten this data, without having to flatten it 4 times?
Data example, staged:
{
"sample": {
"someitem": {
"thesearecool": [
{
"neat": "wow"
},
{
"neat": "tubular"
}
]
}
}
}
I think this works for the first flatten, but is there some way to flatten it two more times, so that each value is in a different column?
select src:sample::string, src:someitem::string, value
from
raw_source
, lateral flatten( input => src:sample )
Source: https://community.snowflake.com/s/article/How-To-Lateral-Join-Tutorial
Do you want to list the values of the neat values?
with raw_source as (select parse_json('{
"sample": {
"someitem": {
"thesearecool": [
{
"neat": "wow"
},
{
"neat": "tubular"
}
]
}
}
}') c)
select f.value:neat as neat
from
raw_source
, lateral flatten( input => c, path => 'sample.someitem.thesearecool' ) f;
In this case, you can use path parameter.
I've found the flatten function but the example is simpler than my real example. It can be created with the following code:
create or replace table test2 as
select '5dd17ef333de385a360e0ef1' as id,
parse_json('{
"_id" : "5dd17ef333de385a360e0ef1",
"uid" : "5dd175d3333b85961df27c51",
"task_info" : {
"reps=1" : [
[
{
"cached" : false,
"transform max RAM" : 51445000,
}
],
[
{
"cached" : false,
"transform max RAM" : 51445000,
}
],
[
{
"cached" : true,
"transform max RAM" : 51445000,
}
]
]
}
}')::variant as json_rec
;
Then my attempt to parse it:
select id
, json_rec:_id::string(100) as extracted_id
, value:cached::string as cached
, value
, json_rec
from
test2
, lateral flatten( input => json_rec:task_info )
;
The cached is clearly not going deep enough, although I am unclear of the syntax that is required to fish something like these values out. Thoughts?
If what you want is a separate row for each of the items in the innermost array (i.e. 3 rows for the above example), then you can use recursive=>true and filter on key='cached', like this:
select id
, json_rec:_id::string(100) as extracted_id
, value as cached
, json_rec
from
test2
, lateral flatten( input => json_rec:task_info, recursive=>true)
where key='cached';
I have JSON values like this stored in a table:
{
"properties":[
{
"address":{
"value":"A3",
"name":"",
"prop":"",
"path":[
"RealOptionsList9293"
],
"type":"local"
},
"value":{
"type":11,
"value":"portland"
},
"dependents":[
],
"save":true
}
]
}
I'd like to index on address.value and value.value so that I can query on them. MSDN examples are for basic property using computed column. It does not cover indexing an array. Is indexing possible on array? Any example will be helpful.
I'd like to query for rows with:
JSON_VALUE(mycolumn, '$.properties[*].address.value') = 'A3'
AND JSON_VALUE(mycolumn, $.properties[*].value.value) = 'portland'
I don't see [*] syntax. Should I use OPENJSON() instead? If I use it, should I use a materialized view?
If you want to query a JSON array, OPENJSON() is more appropriate:
Table:
CREATE TABLE #Data (
JsonData nvarchar(max)
)
INSERT INTo #Data (JsonData)
VALUES (N'{
"properties":[
{
"address":{
"value":"A3",
"name":"",
"prop":"",
"path":[
"RealOptionsList9293"
],
"type":"local"
},
"value":{
"type":11,
"value":"portland"
},
"dependents":[
],
"save":true
},
{
"address":{
"value":"A4",
"name":"",
"prop":"",
"path":[
"RealOptionsList9293"
],
"type":"local"
},
"value":{
"type":11,
"value":"portland"
},
"dependents":[
],
"save":true
}
]
}')
Statement:
SELECT d.*
FROM #Data d
CROSS APPLY OPENJSON(d.JsonData, '$.properties') WITH (
AddressValue nvarchar(1000) '$.address.value',
ValueValue nvarchar(1000) '$.value.value'
) j
WHERE j.AddressValue = 'A3' AND ValueValue = 'portland'
When you want to query JSON arrays or objects you should use JSON_QUERY which is designed to work with that. JSON_VALUE is designed to return a scalar, thus, if you use JSON_VALUE with address, value or even dependents (in your JSON), it'll always returns null. But if you use it with save, it'll return its value.
So, what you need to do is something like this :
SELECT
JSON_VALUE([Address],'$.value')
FROM (
SELECT
JSON_QUERY(#json,'$.properties[0].address') AS [Address]
, JSON_QUERY(#json,'$.properties[0].value') AS [Value]
, JSON_QUERY(#json,'$.properties[0].dependents') AS [dependents]
) arrays
{
"studentID": 1,
"StudentName": "jhon",
"Data":{
"schoolname":"school1",
"enrolmentInfo":
[{
"year":"2015",
"info":
[
{
"courseID":"csc213",
"school":"IT",
"enrollmentdate":"2015-01-01",
"finshdate":"2015-07-01",
"grade": 80 },
{
"courseID":"csc113",
"school":"IT1",
"enrollmentdate":"2015-09-02",
"finshdate":null,
"grade": 90 } ]
},
{
"year":"2014",
"info":
[{
"courseID":"info233",
"school":"IT",
"enrollmentdate":"2014-03-11",
"finshdate":"2014-09-01",
"grade": 81 },
{
"courseID":"csc783",
"school":"IT",
"enrollmentdate":"2014-01-02",
"finshdate":"2014-08-01",
"grade": 87 } ]
} ]
}
}
I have stored in postgresql database json objects of the above format. Each object consists of informations about a certain student with enrollment information. I have complex objects with nested array inside arrays. I am trying to select all the element inside the "info" array. I tried to use the following query:
with recursive x (info) as (select value->'info' from jsontesting r, json_array_elements(r.data->'Data'->'enrolmentinfo')
UNION ALL
SELECT (e).value->'courseID', (e).value->'school', (e).value->'grade',(e).value->'enrollmentdate', (e).value->'finshdate'
from (select json_each(json_array_elements (info)) e from x) p)
select * from x;
This query is not working and it is giving the following error:"cannot call json_array_elements on a scalar". Is there any other query that I can use to extract the elements of the nested array "info"??
-- assuming that jsontesting.data contains your JSON
WITH info_data AS (
SELECT enrolment_info->'info' AS info
FROM jsontesting t, json_array_elements(t.data -> 'Data' -> 'enrolmentInfo') AS enrolment_info
)
SELECT info_item->>'courseID',
info_item->>'school',
info_item->>'enrollmentdate',
info_item->>'finshdate',
info_item->>'grade'
FROM info_data idata, json_array_elements(idata.info) AS info_item;