Alok
Alok

Reputation: 10534

nested json aggregated rows on group by in postgresql

I have a postgresql table

alok=# select * from people;
  name   | country |  city   
---------+---------+---------
 alok    | india   | delhi
 ram     | india   | kolkata
 shyam   | india   | kanpur
 krishna | us      | newyork
 ajit    | india   | delhi
 sami    | india   | delhi
 mohamad | india   | kolkata
(7 rows)

which can be produced by

create table people(name varchar, country varchar, city varchar);

insert into people values('alok', 'india', 'delhi');
insert into people values('ram', 'india', 'kolkata');
insert into people values('shyam', 'india', 'kanpur');
insert into people values('krishna', 'us', 'newyork');
insert into people values('ajit', 'india', 'delhi');
insert into people values('sami', 'india', 'delhi');
insert into people values('mohamad', 'india', 'kolkata');

I want to produce aggregated name on country and city like

country |                name                
---------+------------------------------------
 india   | {"delhi":["alok", "ajit", "sami"], "kolkata":["ram", "mohamad"], "kanpur":["shyam"]}
 us      | {"newyork":["krishna"]}

Upvotes: 2

Views: 289

Answers (2)

Shashank Shandilya
Shashank Shandilya

Reputation: 39

select 
   country, json_agg( json_build_object( 'city', city, 'name', name  ) ) 
from (
   select country, city, json_agg( name ) as name
   from people
   group by country, city 
) a 
group by a.country;

Upvotes: 0

S-Man
S-Man

Reputation: 23676

demo:db<>fiddle

SELECT 
    country,
    json_object_agg(city, agg_names)
FROM (
    SELECT
        country,
        city, 
        json_agg(name) AS agg_names
    FROM
        people
    GROUP BY country, city
) s
GROUP BY country
  1. Group the names by city. To put the names into one JSON array you can use the aggregate function json_agg()
  2. Group this result by the country. To get the expected output you need to use the aggregate function json_object_agg() which creates key/pair values from city and name array

documentation

Upvotes: 3

Related Questions