Postgres JSONB query about nested/recursive elements - sql

I have a nested and hierarchical structure expressed in JSON e.g.:
{
"id":1,
"children": [
{ "id":2 },
{ "id": 3, "children": [
{ "id": 4 }
]
}
]
}
Can postgres answer a query whether the record contains "id": 4 in any part of the document?
If yes, are such queries backed by JSONB indexing added in version 9.4?

UPDATE: Thanks to therealgaxbo on reddit, we started with my original code and developed something more concise:
with recursive deconstruct (jsonlevel) as(
values ('{"id":1,"children":[{"id":2},{"id":3,"children":[{"id":4}]}]}'::json)
union all
select
case left(jsonlevel::text, 1)
when '{' then (json_each(jsonlevel)).value
when '[' then json_array_elements(jsonlevel)
end as jsonlevel
from
deconstruct
where
left(jsonlevel::text, 1) in ('{', '[')
)
select * from deconstruct where case when left(jsonlevel::text, 1) = '{' then jsonlevel->>'id' = '4' else false end;
My original response below:
I experimented like crazy and finally came up with something like this:
with recursive ret(jsondata) as
(select row_to_json(col)::text jsondata from
json_each('{
"id":1,
"children": [
{ "id":2 },
{ "id": 3, "children": [
{ "id": 4 }
]
}
]
}'::json) col
union
select case when left(jsondata::text,1)='[' then row_to_json(json_each(json_array_elements(jsondata)))::text
when left((jsondata->>'value'),2)='{}' then null::text
when left((jsondata->>'value')::text,1)='[' then row_to_json(json_each(json_array_elements(jsondata->'value')))::text
else ('{"key":'||(jsondata->'key')||', "value":'||(jsondata->'value')||'}')::json::text end jsondata
from (
select row_to_json(json_each(ret.jsondata::json)) jsondata
from ret) xyz
)
select max(1) from ret
where jsondata::json->>'key'='id'
and jsondata::json->>'value'='1'

Related

How to Extract the Fields in Bigquery in Nested JSON

I have the following BigQuery :
select JSON_EXTRACT_SCALAR(payload, "$.payload") from mytable
It returns this result :
[
{
"productInfo": {
"productId": "123",
"productType": "Dolls"
},
"storefrontPricingList": [
{
"currentPrice": {
"unitValue": {
"currencyAmount": 10,
"currencyUnit": "USD"
},
"currentValue": {
"currencyAmount": 10,
"currencyUnit": "USD"
},
"variableUnitValue": {
"currencyAmount": 10,
"currencyUnit": "USD"
},
"sellValue": {
"currencyAmount": 10,
"currencyUnit": "USD"
},
"type": "EA"
},
"currentPriceType": "OKAY"
}
]
}
]
Now i want to access theses attributes productInfo.productId , currentPrice.unitValue.currencyAmount.
How we can access these elements i tries couple of things but all giving me null :
Like
select JSON_EXTRACT_SCALAR(payload, "$.payload[0].productInfo.productId") from mytable
select JSON_EXTRACT_SCALAR(payload, "$.payload[0].storefrontPricingList[0]. currentPrice. unitValue. currencyAmount") from mytable
Can you try this ?
-- Declaring a bigQuery variable
DECLARE json_data JSON DEFAULT (SELECT PARSE_JSON('{"payload": [{"productInfo": {"productId": "123","productType": "Dolls" },"storefrontPricingList": [{"currentPrice": {"unitValue": {"currencyAmount": 10,"currencyUnit": "USD"},"currentValue": {"currencyAmount": 10,"currencyUnit": "USD"},"variableUnitValue": {"currencyAmount": 10,"currencyUnit": "USD"},"sellValue": {"currencyAmount": 10,"currencyUnit": "USD"},"type": "EA"},"currentPriceType": "OKAY"}]}]}'));
-- Select statement for extraction
select ARRAY(
SELECT JSON_EXTRACT_SCALAR(payload, '$.productInfo.productId') from UNNEST(JSON_EXTRACT_ARRAY(json_data,"$.payload"))payload
)extracted_productID,
ARRAY(
SELECT JSON_EXTRACT_SCALAR(payload, '$.storefrontPricingList[0].currentPrice.unitValue.currencyAmount') from UNNEST(JSON_EXTRACT_ARRAY(json_data,"$.payload"))payload
)extracted_currencyAmount
Used combination of Array function and Json function for BQ.
Output:

I want to combine json rows in t-sql into single json row

I have a table
id
json
1
{"url":"url2"}
2
{"url":"url2"}
I want to combine these into a single statement where the output is :
{
"graphs": [
{
"id": "1",
"json": [
{
"url": "url1"
}
]
},
{
"id": "2",
"json": [
{
"url": "url2"
}
]
}
]
}
I am using T-SQL, I've notice there is some stuff in postgres but can't find much on tsql.
Any help would be greatly appreciated..
You need to use JSON_QUERY on the json column to ensure it is not escaped.
SELECT
id,
JSON_QUERY('[' + json + ']')
FROM YourTable t
FOR JSON PATH, ROOT('graphs');
db<>fiddle

Postgreql json data how to list all elements of an array

I have a jsonB field in postgresql DB table, it has data like this
{
"units": [
{
"id": 299872379221376,
"unitNumber": "1",
"unitFloorSpace": 1,
"createdTimeStamp": 1587994498586
},
{
"id": 299872417011074,
"unitNumber": "2",
"unitFloorSpace": 2,
"createdTimeStamp": 1588001330085
}
]
}
I just want to list all unitNumbers like below, what would be the query for that?
1,
2,
I have tried below json query but that doesn’t list
Select form_data -> units -> unitNumbers from table where row_id =1;
here is one way:
select jsonb_array_elements(jsonb_extract_path(jdata,'units')) ->> 'unitNumber' as UnitNumber
from tableName;
db<>fiddle here

How to unpack Array to Rows in Snowflake?

I have a table that looks like the following in Snowflake:
ID | CODES
2 | [ { "list": [ { "item": "CODE1" }, { "item": "CODE2" } ] } ]
And I want to make it into:
ID | CODES
2 | 'CODE1'
2 | 'CODE2'
So far I've tried
SELECT ID,CODES[0]:list
FROM MY_TABLE
But that only gets me as far as:
ID | CODES
2 | [ { "item": "CODE1" }, { "item": "CODE2" } ]
How can I break out every 'item' element from every index of this list into its own row with each CODE as a string?
Update: Here is the answer I got working at the same time as the answer below, looks like we both used FLATTEN:
SELECT ID,f.value:item
FROM MY_TABLE,
lateral flatten(input => MY_TABLE.CODES[0]:list) f
So as you note you have hard coded your access into the codes, via codes[0] which gives you the first item from that array, if you use FLATTEN you can access all of the objects of the first array.
WITH my_table(id,codes) AS (
SELECT 2, parse_json('[ { "list": [ { "item": "CODE1" }, { "item": "CODE2" } ] } ]')
)
SELECT ID, c.*
FROM my_table,
table(flatten(codes)) c;
gives:
2 1 [0] 0 { "list": [ { "item": "CODE1" }, { "item": "CODE2" }]} [ { "list": [{"item": "CODE1"}, { "item": "CODE2" }]}]
so now you want to loop across the items in list, so we use another FLATTEN on that:
WITH my_table(id,codes) AS (
SELECT 2, parse_json('[ { "list": [ { "item": "CODE1" }, { "item": "CODE2" } ] } ]')
)
SELECT ID, c.value, l.value
FROM my_table,
table(flatten(codes)) c,
table(flatten(c.value:list)) l;
gives:
2 {"list":[{"item": "CODE1"},{"item":"CODE2"}]} {"item":"CODE1"}
2 {"list":[{"item": "CODE1"},{"item":"CODE2"}]} {"item":"CODE2"}
so you can pull apart that l.value how you need to access the parts you need.

Take json value in sql without JSON_VALUE

i want to take value (In SQL Server) in json object without JSON_VALUE
The json value :
{{
"Url": "****",
"Token": "",
"Data": {
"role_id": 1001,
"data": {
"stringvalue": [
{
"minage": "21"
},
{
"maxage": "55"
},
{
"primary_identity_file": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAgAAAQABAAD/7QCcUGhvdG9zaG9wIDMuMAA4QklNBAQAAAAAAIAcAmcAFHpFZEQyY1ZzbGVyRzNrcF8yTjhHHAIoAGJGQk1EMDEwMDBhYzAwMzAwMDAwMjMxMDAwMDQxNzQwMDAwYjQ3YjAwMDBhMTgyMDAwMDliY2EwMDAwMjkyMDAxMDBmODJhMDEwMGFiMzQwMTAwMDgzZTAxMDBjZGM0MDEwMP/iAhxJQ0NfUFJPRklMRQABAQAAAgxsY21zAhAAAG1udHJSR0IgWFlaIA"
}
]
}
}
}}
what i trying to do is to take "primary_identity_file" value
the result should be :
data:image/jpeg;base64,/9j/4AAQSkZJRgABAgAAAQABAAD/7QCcUGhvdG9zaG9wIDMuMAA4QklNBAQAAAAAAIAcAmcAFHpFZEQyY1ZzbGVyRzNrcF8yTjhHHAIoAGJGQk1EMDEwMDBhYzAwMzAwMDAwMjMxMDAwMDQxNzQwMDAwYjQ3YjAwMDBhMTgyMDAwMDliY2EwMDAwMjkyMDAxMDBmODJhMDEwMGFiMzQwMTAwMDgzZTAxMDBjZGM0MDEwMP/iAhxJQ0NfUFJPRklMRQABAQAAAgxsY21zAhAAAG1udHJSR0IgWFlaIA
** NOTE primary_identity_file value is more than 10K character
I'd try something like that:
select substring(vlv3, 1, charindex('"', vlv3)-1) as vlv4
from (
select substring(vlv2, charindex('"', vlv2)+1, len(vlv2)) as vlv3
from (
select substring(vlv, charindex('"primary_identity_file"', vlv)+23, len(vlv)) as vlv2
from test
) as test2
) as test3
You can rewrite in more readable way as stored procedure
Sample fiddle http://sqlfiddle.com/#!18/a122b/7