DB2 The number of node occurrences in json - sql

I would like to check how many times there is a node "amount" in json.
Does anyone know how I could get this information in DB2?
select count(*)
from (
select json from schema.test1
where lastname = 'Johnson'
) where json like '%amount%'

Related

Postgresql JSON column check value exists in array of json

I have a database schema like the following where I have a Children record table
CREATE TABLE Children (
name varchar(100),
friends JSON NOT NULL,
);
INSERT INTO Children (name,friends)
VALUES('Sam',
array['{"name":"Rakesh","country":"Africa"}',
'{"name":"Ramesh","country":"India"}']::json[]);
Now I need to query the data and display it only if the name of the friend is like '%Ra'. Structure of the JSON data is consistent.
If you have json[] as data type then you can use unnest and then write your query, or if it is json then you can use json_array_elements.
Below code considers json[] data type -
select * from Children
where name in (
select name from (
select name, unnest(friends) as friend from Children
) i
where i.friend->>'name' like '%Ra');
DBFiddle

How to execute a select with a WHERE using a not-always-existing column

Simple example: I have some (nearly) identical tables with personal data (age, name, weight, ...)
Now I have a simple, but long SELECT to find missing data:
Select ID
from personal_data_a
where
born is null
or age < 1
or weight > 500
or (name is 'John' and surname is 'Doe')
Now the problem is:
I have some personal_data tables where the column "surname" does not exit, but I want to use the same SQL-statement for all of them. So I have to check (inside the WHERE clause) that the last OR-condition is only used "IF the column surname exists".
Can it be done in a simple way?
You should have all people in the same table.
If you can't do that for some reason, consider creating a view. Something like this:
CREATE OR REPLACE VIEW v_personal_data
AS
SELECT id,
born,
name,
surname,
age,
weight
FROM personal_data_a
UNION ALL
SELECT id,
born,
name,
NULL AS surname, --> this table doesn't contain surname
age,
weight
FROM personal_data_b;
and then
SELECT id
FROM v_personal_data
WHERE born IS NULL
OR age < 1
OR ( name = 'John'
AND ( surname = 'Doe'
OR surname IS NULL))
Can it be done in a simple way?
No, SQL statements work with static columns and the statements will raise an exception if you try to refer to a column that does not exist.
You will either:
need to have a different query for tables with the surname column and those without;
have to check in the data dictionary whether the table has the column or not and then use dynamic SQL to build your query; or
to build a VIEW of the tables which do not have that column and add the column to the view (or add a GENERATED surname column with a NULL value to the tables that are missing it) and use that instead.
While dynamic predicates are usually best handled by the application or by custom PL/SQL objects that use dynamic SQL, you can solve this problem with a single SQL statement using DBMS_XMLGEN, XMLTABLE, and the data dictionary. The following code is not what I would call "simple", but it is simple in the sense that it does not require any schema changes.
--Get the ID column from a PERSONAL table.
--
--#4: Get the IDs from the XMLType.
select id
from
(
--#3: Convert the XML to an XMLType.
select xmltype(personal_xml) personal_xmltype
from
(
--#2: Convert the SQL to XML.
select dbms_xmlgen.getxml(v_sql) personal_xml
from
(
--#1: Use data dictionary to create SQL statement that may or may not include
-- the surname predicate.
select max(replace(replace(
q'[
Select ID
from #TABLE_NAME#
where
born is null
or age < 1
or weight > 500
or (name = 'John' #OPTIONAL_SURNAME_PREDICATE#)
]'
, '#TABLE_NAME#', table_name)
, '#OPTIONAL_SURNAME_PREDICATE#', case when column_name = 'SURNAME' then
'and surname = ''Doe''' else null end)) v_sql
from all_tab_columns
--Change this literal to the desired table.
where table_name = 'PERSONAL_DATA_A'
)
)
where personal_xml is not null
)
cross join xmltable
(
'/ROWSET/ROW'
passing personal_xmltype
columns
id number path 'ID'
);
See this db<>fiddle for a runnable example.

How to convert double quoted ids to single quoted ids so that it is queryable in postgres?

PostgreSQL version: 10.3
Schema of product
id integer
data text
Schema of color
id integer
name text
Color of a product is stored within data as array of colorids ex: ['1','2'].
I need a query wherein I could get the color id and name for a particular product.
Tried something like this and got error:
select id,name from colors where id in (select trim(data::json ->> 'color_ids','[]') from products where id = 1);
ERROR: operator does not exist: integer = text
I tried this:
query:
select data::json ->> 'color_ids' from products where id = 1;
result:
["2","5","6","14"]
query:
select trim(data::json ->> 'color_ids','[]') from products where id = 1;
result:
"2","5","6","14"
I would also suggest making it a integer (int). Does it work when you put a replace around it?
replace (trim(data::json ->> 'color_ids','[]'), '"', '')

Getting values from array of objects jsonb postgresql

I am storing some ids and names in a jsonb array of object like this
[{"id":"1","name":"abc"},{"id":"2","name":"cde"}]
My table looks like this
id userinfo
1 [{"id":"1","name":"abc"},{"id":"2","name":"cde"}]
2 [{"id":"3","name":"fgh"},{"id":"4","name":"ijk"}]
I am trying to select all the records with id 1 but I just want to get ids in userinfo object I don't want names
I tried this
select distinct userinfo->'name' from table where id = 1
but this is giving me null value
This will work with this query
select distinct userinfo->0->'name' from table where id = 1
but I don't know the index so how can I use this query to get my desired result
Thanks
You need to normalize the data by unnesting the array, then you can access each element.
select ui.info ->> 'id' as id,
ui.info ->> 'name' as name
from the_table t
cross join lateral jsonb_array_elements(t.userinfo) as ui(info)
where t.id = 1;
Online example: http://rextester.com/FCNM11312

How to use other table JSON data in select query

I am using postgres and have 2 tables, deviceTble has the following columns: deviceName, device_id, type, deviceOwnerPerson_id, deviceAccessPerson_id.
The other table is Person_kv and has 2 columns id,data (containing person info but in JSON format).
I want to a select query from deviceTble and want to use first_name and last_name of a person which are in Person_kv table by given of deviceOwnerPersonId and deviceAccessPersonId.
Here is what I have to get data from person_kv table to get data in tabular form:
select data :: json ->> 'id' as id
, data :: json ->> 'name' as first_name
, data :: json ->> 'surename' as last_name
from Person_kv
and expected deviceTble query:
select deviceName,device_id,type from deviceTble
I am confused either I use WITH clause on person_kv query and then join here or one by one on deviceOwnerPerson_id and deviceAccessPerson_id OR is there any other way as well by using inner query
Can someone tell me how I can get required result?
from you description you can just join em:
select deviceName,device_id,type, p.data:: json ->>'name' , p.data:: json ->>'surname'
from deviceTble d
join Person_kv p on p.data:: json ->>'id' = deviceOwnerPerson_id::text OR p.data:: json ->>'id' = deviceAccessPerson_id::text