how sum column group by jsonḃ postgres - json

Hi I have a colum jsnoḃ with this values
proyectos:
nomḃre:character_varying
fecha:datetime
campos: jsonḃ
the value of campos is =
{"lista": [{"valor": "10", "nombre": "sueldo"}, {"valor": "20", "nombre": "sueldo"}, {"valor": "25", "nombre": "sueldo"}]}
I I run this query ḃut not working
SELECT jsonb_array_elements(campos->'lista')->'nombre' as content,
sum(((jsonb_array_elements(campos->'lista')->'valor'))::numeric) as cantidad
FROM proyectos GROUP BY jsonb_array_elements(campos->'lista')->'nombre
The console show me the message:
ERROR: cannot cast type jsonb to numeric
LINE 3: ...((jsonb_array_elements(campos->'lista')->'valor'))::numeric)...
^
********** Error **********
ERROR: cannot cast type jsonb to numeric
SQL state: 42846
Character: 137
Any idea ?

Use the function jsonb_array_elements() in a lateral join to get array elements as value, the ->> operator to get json objects as text and cast the valor objects to numeric.
select value->>'nombre' as nombre, sum((value->>'valor')::numeric)
from proyectos
cross join jsonb_array_elements(campos->'lista')
group by 1
nombre | sum
--------+-----
sueldo | 55
(1 row)

Related

Oracle select JSON column as key / value table [duplicate]

This question already has an answer here:
Query json dictionary data in SQL
(1 answer)
Closed 1 year ago.
In Oracle 12c, having a column with JSON data in this format:
{
"user_name": "Dave",
"phone_number": "13326415",
"married": false,
"age": 18
}
How can I select it in this format:
key val
-------------- ----------
"user_name" "Dave"
"phone_number" "13326415"
"married" "false"
"age" "18"
As stated in the comment, there is no way to get the keys of a JSON object using just SQL. With PL/SQL you can create a pipelined function to get the information you need. Below is a very simple pipelined function that will get the keys of a JSON object and print the type each key is, as well as the key name and the value.
First, you will need to create the types that will be used by the function
CREATE OR REPLACE TYPE key_value_table_rec FORCE AS OBJECT
(
TYPE VARCHAR2 (100),
key VARCHAR2 (200),
VALUE VARCHAR2 (200)
);
/
CREATE OR REPLACE TYPE key_value_table_t AS TABLE OF key_value_table_rec;
/
Next, create the pipelined function that will return the information in the format of the types defined above.
CREATE OR REPLACE FUNCTION get_key_value_table (p_json CLOB)
RETURN key_value_table_t
PIPELINED
AS
l_json json_object_t;
l_json_keys json_key_list;
l_json_element json_element_t;
BEGIN
l_json := json_object_t (p_json);
l_json_keys := l_json.get_keys;
FOR i IN 1 .. l_json_keys.COUNT
LOOP
l_json_element := l_json.get (l_json_keys (i));
PIPE ROW (key_value_table_rec (
CASE
WHEN l_json_element.is_null THEN 'null'
WHEN l_json_element.is_boolean THEN 'boolean'
WHEN l_json_element.is_number THEN 'number'
WHEN l_json_element.is_timestamp THEN 'timestamp'
WHEN l_json_element.is_date THEN 'date'
WHEN l_json_element.is_string THEN 'string'
WHEN l_json_element.is_object THEN 'object'
WHEN l_json_element.is_array THEN 'array'
ELSE 'unknown'
END,
l_json_keys (i),
l_json.get_string (l_json_keys (i))));
END LOOP;
RETURN;
EXCEPTION
WHEN OTHERS
THEN
CASE SQLCODE
WHEN -40834
THEN
--JSON format is not valid
NULL;
ELSE
RAISE;
END CASE;
END;
/
Finally, you can call the pipelined function from a SELECT statement
SELECT * FROM TABLE (get_key_value_table (p_json => '{
"user_name": "Dave",
"phone_number": "13326415",
"married": false,
"age": 18
}'));
TYPE KEY VALUE
__________ _______________ ___________
string user_name Dave
string phone_number 13326415
boolean married false
number age 18
If your JSON values are stored in a column in a table, you can view the keys/values using CROSS JOIN
WITH
sample_table (id, json_col)
AS
(SELECT 1, '{"key1":"val1","key_obj":{"nested_key":"nested_val"},"key_bool":false}'
FROM DUAL
UNION ALL
SELECT 2, '{"key3":3.14,"key_arr":[1,2,3]}' FROM DUAL)
SELECT t.id, j.*
FROM sample_table t CROSS JOIN TABLE (get_key_value_table (p_json => t.json_col)) j;
ID TYPE KEY VALUE
_____ __________ ___________ ________
1 string key1 val1
1 object key_obj
1 boolean key_bool false
2 number key3 3.14
2 array key_arr

Get nested objects values from JSON in Postgres

So here is my JSON column in my Postgres DB:
{
"objekt_art": {
"86": {
"code": "86",
"bezeichnung_de": "Kino",
"bezeichnung_fr": "Cinéma",
"bezeichnung_it": "Cinema",
"bezeichnung_en": null,
"kurz_bezeichnung_de": "Kino",
"relevant_fuer_berechnung_steuerquote": true
},
"27": {
"code": "27",
"bezeichnung_de": "Kiosk",
"bezeichnung_fr": "Kiosque",
"bezeichnung_it": "Chiosco",
"bezeichnung_en": null,
"kurz_bezeichnung_de": "Kiosk",
"relevant_fuer_berechnung_steuerquote": true
}
}
}
I need to be able to query the bezechnung_de for example where code = 86.
The number of code i can pass from another table.
How can i for example make a query with two columns. One with the number and the second with bezeichnung_de.
Like this:
Code Bez
86 Kino
Sample data structure and sample table for join data: dbfiddle
select
je.value -> 'code' as "Code",
je.value -> 'bezeichnung_de' as "Bez"
from
test t
cross join jsonb_each((data::jsonb ->> 'objekt_art')::jsonb) je
-- In table test_join I insert value 86 for join record
inner join test_join tj on je.key::int = tj.json_id
As you know the code, this is fairly easy:
select t.the_column -> 'objekt_art' -> '86' ->> 'code' as code,
t.the_column -> 'objekt_art' -> '86' ->> 'bezeichnung_de' as bez
from the_table t
where ...
The value '86' can be a parameter. The first expression to select the code isn't really needed though, as you could replace it with the constant value (=parameter) directly.
If the "outer" JSON key isn't the same value as the code value, you could use something like this:
select o.value ->> 'code' as code,
o.value ->> 'bezeichnung_de' as bez
from the_table t
cross join jsonb_each(t.the_column -> 'objekt_art') o(key, value)
where o.key = '86'
and ... other conditions ...
If you are using Postgres 13 or later, this can also be written as a JSON path expression:
select a.item ->> 'code' as code,
a.item ->> 'bezeichnung_de' as bez
from (
select jsonb_path_query_first(t.the_column, '$.objekt_art.* ? (#.code == "86")') as item
from the_table t
where ....
) a
All examples assume that the column is defined with the data jsonb which it should be. If it's not you need to cast it: the_column::jsonb

List arbitrary number of elements from a json field (postgres)

I have a json field in postgres db that contains data like
[{
"value": "+1 968 730 5680",
"label": "mobile",
"primary": true
},{
"value": "+1 909 169 4444",
"label": "mobile",
"primary": false
}]
I want to query this field to produce
+1 968 730 5680; +1 909 169 4444
Given that the number of elemets can vary.
I had enough brains to get the first element with
json_field -> 0 ->> 'value'
but am totally stuck at producing a string with all elements.
Please help.
UPDATE
Following advice below, I get an error with statement
select d ->> 'value' as val
from analyst.person
cross join jsonb_array_elements(phone) as x(d)
ERROR: column "phone" does not exist
LINE 3: cross join jsonb_array_elements(phone) as x(d)
another variant I tried
select d ->> 'value' as val
from analyst.person as person
cross join jsonb_array_elements(person.phone) as x(d)
gives error
ERROR: invalid reference to FROM-clause entry for table "person"
LINE 3: cross join jsonb_array_elements(person.phone) as x(d)
^
HINT: There is an entry for table "person", but it cannot be referenced from this part of the query.
You need to unnest your json array, extract the value and aggregate it back into a string:
select string_agg(val, '; ')
from (
select d ->> 'value' as val
from the_table
cross join lateral jsonb_array_elements(the_json_colum) as x(d)
) t
Online example: https://rextester.com/VFSRY99127

syntax error when trying to query json documents in postgresql

on my postgresql 9.6, I ran into an error with a table created like
create table jsonTest (id integer, data jsonb);
The table has the following data:
select * from jsonTest;
id | data
----+----------------------------------
1 | {"tags": ["AA", "BB", "CC"]}
2 | {"tags": ["BB", "DD"]}
2 | {"tags": ["CC"]}
4 | {"city": "austin", "tags": "EE"}
(4 rows)
But when I tried to select, got syntax error:
template1=# select * from jsonTest where data->>city = 'austin';
ERROR: column "city" does not exist
LINE 1: select * from jsonTest where data->>city = 'austin';
Any ideas? Thanks a lot!
The right operand of ->> operator for JSON object is text. Use the apostrophes for the key, because without them Postgres interprets the name as an identifier (a column name):
data->>'city'

PostgreSQL script that should parse JSON field to a column gives NULL

Here is my statement:
SELECT
"raw_storage_basetransaction"."id",
"raw_storage_basetransaction"."r_v",
"raw_storage_basetransaction"."transaction_data",
"raw_storage_basetransaction"."entry_datetime",
"raw_storage_basetransaction"."owner_id",
("transaction_data" ->> 'SupplierDB') AS "v"
FROM
"raw_storage_basetransaction"
LIMIT 21
or
SELECT
"raw_storage_basetransaction"."id",
"raw_storage_basetransaction"."r_v",
"raw_storage_basetransaction"."transaction_data",
"raw_storage_basetransaction"."entry_datetime",
"raw_storage_basetransaction"."owner_id",
("raw_storage_basetransaction"."transaction_data" ->> 'SupplierDB') AS "v"
FROM
"raw_storage_basetransaction"
LIMIT 21
v is always NULL
What did I do wrong?
--UPD--
My fault. I wrote in jsonb field a unicode string instead of json-dict.