0

One of the columns in my table, has JSONArray data. I have used jsonb_agg() in a jsonb column to a view. Now the data from view looks like below

[
  {
    "Android": 2,
    "Windows": 1,
    "Macintosh": 1
  },
  {
    "iOS": 1,
    "Android": 2,
    "Windows": 2,
    "Macintosh": 2
  },
  {},
  {
    "Android": 1,
    "Windows": 1
  },
  {
    "Android": 1
  },
  {
    "iOS": 1,
    "Android": 2
  },
  {
    "iOS": 2,
    "Android": 1
  },
  {
    "iOS": 2
  },
  {
    "Android": 1
  },
  {
    "iOS": 2,
    "Windows": 1
  },
  {
    "Android": 5
  },
  {},
  {},
  {
    "iOS": 1,
    "Android": 1
  },
  {},
  {},
  {
    "Windows": 3
  }
]

However, I need to product the below result

{
  "Android": 16,
  "Windows": 8,
  "Macintosh": 3,
  "iOS": 9
}

Is there a way within PostgreSQL to achieve this?

3 Answers 3

1

Yes there is a way. Here it is.

select to_jsonb(t.*) from
(
 select 
    sum((j->>'Android')::numeric) "Android", 
    sum((j->>'Windows')::numeric) "Windows", 
    sum((j->>'Macintosh')::numeric) "Macintosh", 
    sum((j->>'iOS')::numeric) "iOS" 
 from jsonb_array_elements('[{"Android": 2, "Windows": 1, "Macintosh": 1}, {"iOS": 1, "Android": 2, "Windows": 2, "Macintosh": 2}, {}, {"Android": 1, "Windows": 1}, {"Android": 1}, {"iOS": 1, "Android": 2}, {"iOS": 2, "Android": 1}, {"iOS": 2}, {"Android": 1}, {"iOS": 2, "Windows": 1}, {"Android": 5}, {}, {}, {"iOS": 1, "Android": 1}, {}, {}, "Windows": 3}]'::jsonb) as j
) as t;

As a parameterized query:

select to_jsonb(t.*) from
(
 select 
    sum((j->>'Android')::numeric) "Android", 
    sum((j->>'Windows')::numeric) "Windows", 
    sum((j->>'Macintosh')::numeric) "Macintosh", 
    sum((j->>'iOS')::numeric) "iOS" 
 from jsonb_array_elements(?::jsonb) as j
) as t;
Sign up to request clarification or add additional context in comments.

Comments

0

You can use dynamic key, value like that:

with data as (
  select
    je.key,
    sum(je.value::int)
  from 
    json_array_elements('[{"Android": 2, "Windows": 1, "Macintosh": 1}, {"iOS": 1, "Android": 2, "Windows": 2, "Macintosh": 2}, {}, {"Android": 1, "Windows": 1}, {"Android": 1}, {"iOS": 1, "Android": 2}, {"iOS": 2, "Android": 1}, {"iOS": 2}, {"Android": 1}, {"iOS": 2, "Windows": 1}, {"Android": 5}, {}, {}, {"iOS": 1, "Android": 1}, {}, {}, {"Windows": 3}]') d
    cross join json_each_text(d) as je
  group by 1
)
select json_object_agg(d.key, d.sum)
from data d

Or if you have table and column you can use this sample format like that:

with data as (
  select
    je.key,
    sum(je.value::int)
  from 
    your_table t join
    json_array_elements(t.your_json_coulmn) d on true
    cross join json_each_text(d) as je
  group by 1
)
select json_object_agg(d.key, d.sum)
from data d

Comments

0

You can combine many json/jsonb functions to get the result

SELECT
    jsonb_agg(json_build_object(key, sum))
FROM (
    SELECT
        key,
        sum(value)
    FROM (
        SELECT
            (arr).key,
            (arr).value::int
        FROM (
            SELECT
                jsonb_each(j) arr
            FROM (
                SELECT
                    jsonb_array_elements('[{"Android": 2, "Windows": 1, "Macintosh": 1}, {"iOS": 1, "Android": 2, "Windows": 2, "Macintosh": 2}, {}, {"Android": 1, "Windows": 1}, {"Android": 1}, {"iOS": 1, "Android": 2}, {"iOS": 2, "Android": 1}, {"iOS": 2}, {"Android": 1}, {"iOS": 2, "Windows": 1}, {"Android": 5}, {}, {}, {"iOS": 1, "Android": 1}, {}, {}, {"Windows": 3}]
'::jsonb) AS j) AS jpart) AS x) sub
    GROUP BY
        1) AS sub2

output: [{"Windows": 8}, {"Android": 16}, {"iOS": 9}, {"Macintosh": 3}]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.