DB2 Build Json document with about two columns - db2

I want to generate a json file based on the result of this query.
But as a result I will get exactly 10 rows as CLOB. But I want only one.
select json_object (
'ID' value id, 'NAME' value name)
FROM OBJECTS
FETCH FIRST 10 ROWS ONLY
It should has an output like this
{
objects:
{id:1, name: a
},
{id:2, name: b
}
}

Just some guessing:
values (json_array(select json_object ('ID' value id, 'NAME' value name)
from objects
fetch first 10 rows only
)
)
AFAIK, you need an array to store a collection of things:
values json_object( 'objects' value (json_array
(select json_object ('ID' value id, 'NAME' value name)
from objects
fetch first 10 rows only
)
));

Related

Postgres - Query Specific Value in an Array of Arrays

I have column that is returning from my query that is an array of array. It looks like this.
array_vals: {{NULL,NULL,147.89,87.27,82.65,83.41,93.69,101.90,NULL,NULL}}
When I try to query in to my array first array I always get Null values.
select array_vals[0] from table
This returns null. But my desired results would be {NULL,NULL,147.89,87.27,82.65,83.41,93.69,101.90,NULL,NULL}
with test as (
select 1 as value, array_agg(array[1 , 3, 4]) as data
group by value
)
select data[1] from test
This returns null for me.

Postgres - Remove NULL values from a json array

I'm building a JSON ARRAY from a table which has a JSON column and non-JSON columns.
Here is my sample data and query:
create table check_details(SHORT_NAME VARCHAR, UNIQUE_NO JSON,STATUS VARCHAR);
insert into check_details values('Anu','{"ID":"1e699-76af2"}','REJECTED');
select json_agg(json_strip_nulls(
json_build_object('Name',SHORT_NAME,
'IDS',
jsonb_build_array(case SIGN(position('ACCEPTED' in STATUS) ) when 1 then UNIQUE_NO::jsonb->>'ID' else json_typeof(NULL::json) end)
)))
from check_details;
I am getting this result:
[{"Name":"Anu","IDS":[null]}]
But I do not want to get "IDS":[null] part in my result when the value of the key IDS is NULL.
How can I achieve this result:
[{"Name":"Anu"}]
When IDS has a valid value, it has to be an array. Hence using jsonb_build_array.
This is because you are placing the result of your CASE statement in a JSON array, so it's a non-empty array containing a JSON null rather than null JSON value.
So you would need to stop that being an array if you want the NULL to be stripped:
SELECT
json_strip_nulls(
json_build_object(
'Name',
short_name,
'IDS',
CASE SIGN(position('ACCEPTED' IN status) )
WHEN 1 THEN (unique_no::jsonb->>'ID')::text
ELSE NULL
END
)
)
FROM
check_details;
json_strip_nulls
------------------
{"Name":"Anu"}
(1 row)
Note that json_strip_nulls() doesn't remove null values from JSON arrays.
Edit:
But as you require non-null values to show as an array, move the jsonb_build_array() function into the case statement
SELECT
json_strip_nulls(
json_build_object(
'Name',
short_name,
'IDS',
CASE SIGN(position('ACCEPTED' IN status) )
WHEN 1 THEN jsonb_build_array((unique_no::jsonb->>'ID')::text)
ELSE NULL
END
)
)
FROM
check_details;

Updating JSON column in Postgres?

I've got a JSON column in Postgres, that contains data in the following structure
{
"listings": [{
"id": "KTyneMdrAhAEKyC9Aylf",
"active": true
},
{
"id": "ZcjK9M4tuwhWWdK8WcfX",
"active": false
}
]
}
I need to do a few things, all of which I am unsure how to do
Add a new object to the listings array
Remove an object from the listings array based on its id
Update an object in the listings array based on its id
I am also using Sequelize if there are any built in functions to do this (I can't see anything obvious)
demo:db<>fiddle
Insert (jsonb_insert()):
UPDATE mytable
SET mydata = jsonb_insert(mydata, '{listings, 0}', '{"id":"foo", "active":true}');
Update (expand array, change value with jsonb_set(), reaggregate):
UPDATE mytable
SET mydata = jsonb_set(mydata, '{listings}', s.a)
FROM
(
SELECT
jsonb_agg(
CASE WHEN elems ->> 'id' = 'foo' THEN jsonb_set(elems, '{active}', 'false')
ELSE elems
END
) as a
FROM
mytable,
jsonb_array_elements(mydata -> 'listings') AS elems
) s;
Delete (expand array, filter relevant elements, reaggregate):
UPDATE mytable
SET mydata = jsonb_set(mydata, '{listings}', s.a)
FROM
(
SELECT
jsonb_agg(elems) as a
FROM
mytable,
jsonb_array_elements(mydata -> 'listings') AS elems
WHERE elems ->> 'id' != 'foo'
) s;
Updating and deleting can be done in one line like the inserting. But in that case you have to use the array element index instead of a certain value. If you want to change an array element with a value you need to read it first. This is only possible with a prior expanding.

How to filter data from postgresql which has jsonb nested field in the array field of jsonb?

i have a table with a jsonb column and documents are like these(simplified)
{
"a": 1,
"rg": [
{
"rti": 2
}
]
}
I want to filter all the rows which has 'rg' field and there is at least one 'rti'field in the array.
My current solution is
log->>'rg' ilike '%rti%'
Is there another approach, probably a faster solution exists.
Another approach would be applying jsonb_each to the jsonb object and then jsonb_array_elements_text to the extracted value from jsonb_each method :
select id, js_value2
from
(
select (js).value as js_value, jsonb_array_elements_text((js).value) as js_value2,id
from
(
select jsonb_each(log) as js, id
from tab
) q
where (js).key = 'rg'
) q2
where js_value2 like '%rti%';
Demo

Postgresql query json element inside json array

I have a table like:
CREATE TABLE stats
(
item character varying,
data jsonb
);
it contains values like
ITEM DATA
test1 [{"id":"1", "country":"UK"},{"id":"2", "country":"INDIA"}]
test2 [{"id":"1", "country":"US"},{"id":"4", "country":"CHINA"},{"id":"5", "country":"CHINA"}]
I need to get number of distinct json objects where country is 'CHINA' and item is '%test%';
In this case the output should be 2, ie, [{"id":"4", "country":"CHINA"},{"id":"5", "country":"CHINA"}]
I am using the following query
SELECT * FROM stats t
WHERE ( data #> '[{"country":"CHINA"}]')
and t.item ilike '%test%';
output : [{"id":"1", "country":"US"},{"id":"4", "country":"CHINA"},{"id":"5", "country":"CHINA"}]
What should i do so that i get the array of objects which has 'CHINA' as countries?
Use jsonb_array_elements() to get single json objects, filter them and use jsonb_agg() to aggregate into a json array.
select item, jsonb_agg(obj)
from stats, jsonb_array_elements(data) obj
where obj->>'country' = 'CHINA'
group by 1;