简体   繁体   中英

Query Sum of jsonb column of objects

I have a jsonb column on my DB called reactions which has the structure like below.

[
   {
     "id": "1234",
     "count": 1
   },
   {
     "id": "2345",
     "count": 1
   }
]

The field holds an array of objects, each with a count and id field. I'm trying to find which object in the reactions field has the highest count across the db. Basically, I'd like to sum each object by it's id and find the max.

I've figured out how to sum up all of the reaction counts, but I'm getting stuck grouping it by the ID, and finding the sum for each individual id.

SELECT SUM((x->>'count')::integer) FROM (SELECT id, reactions FROM messages) as m
       CROSS JOIN LATERAL jsonb_array_elements(m.reactions) AS x 

Ideally I'd end up with something like this:

id   | sum 
-----------
1234 | 100
2345 | 70
5678 | 50

The messages table looks something like this

id | user | reactions
------------------------
1  | 3456 | jsonb
2  | 8573 | jsonb

The data calculation needs to take some transformation steps.

  1. flat the jsonb column from array to individual jsonb objects using jsonb_array_elements function;
postgres=# select jsonb_array_elements(reactions)::jsonb as data from messages;
            data            
----------------------------
 {"id": "1234", "count": 1}
 {"id": "2345", "count": 1}
 {"id": "1234", "count": 1}
 {"id": "2345", "count": 1}
...

  1. populate each jsonb objects to seperate columns with jsonb_populate_record function;
postgres=# create table data(id text ,count int);
CREATE TABLE

postgres=# select r.* from (select jsonb_array_elements(reactions)::jsonb as data from messages) as tmp, jsonb_populate_record(NULL::data, data) r;
  id  | count 
------+-------
 1234 |     1
 2345 |     1
 1234 |     1
 2345 |     1
...
  1. do the sum with group by .
postgres=# select r.id, sum(r.count) from (select jsonb_array_elements(reactions)::jsonb as data from messages) as tmp, jsonb_populate_record(NULL::data, data) r group by r.id;
  id  | sum 
------+-----
 2345 |   2
 1234 |   2
...

The above steps should make it.

you can use the below - to convert the jsonb array to standard rows

see https://dba.stackexchange.com/questions/203250/getting-specific-key-values-from-jsonb-into-columns

select "id", sum("count")
  from messages
  left join lateral jsonb_to_recordset(reactions) x ("id" text, "count" int) on true
group by "id" order by 1;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM