I'm trying to create a VIEW
of a JSON object, with a varying number of key/value pairs, in PostgreSQL v14.x, from the results of a SELECT statement.
Using json_agg
is returning an array of objects - a key of each rating possibility as they occur, and a value which is the count of all the ratings selected from a table of reviews.
Instead of an array, I need an object that has multiple key/value pairs, where the value corresponds to the aggregated count()
of the ratings column(s), grouped by product_id. Trying to reuse json_build_object
isn't working as expected.
Using:
CREATE VIEW reviews.meta AS
SELECT product_id, json_agg(json_build_object(reviews.list.rating, reviews.list.rating))
FROM reviews.list
GROUP BY reviews.list.product_id
ORDER BY product_id;
returns:
product_id | reviews_count
---------------------------
1 | [{"5" : 5}, {"4" : 4}]
2 | [{"4" : 4}, {"4" : 4}, {"3" : 3}, {"5" : 5}, {"2" : 2}]
But I'm looking for:
product_id | reviews_count
---------------------------
1 | {"5" : 1, "4" : 1}
2 | {"4" : 2, "3" : 1, "5" : 1, "2" : 1}
A dynamically created object:
- in rows by product_id
- where the values are quantities of Integer ratings (1-5) as they appear in the reviews.list table
- in an object rather than an array of objects
New to SQL / PL/pgSQL language, any tips would be appreciated!
Happy early Thanksgiving :)
CodePudding user response:
You need two levels of aggregation, one to get the counts, and one to package the counts up. It is easy to do that by nesting one query inside the FROM of another:
CREATE or replace VIEW meta AS
SELECT product_id, jsonb_object_agg(rating, count)
FROM (select product_id, rating, count(*) from list group by product_id, rating) foo
GROUP BY product_id
ORDER BY product_id;