如何在 Postgres 的 json_build_object() 中进行 GROUP BY 和 COUNT

How to do a GROUP BY and COUNT within json_build_object() in Postgres

我想在 table(或 CTE)上执行多个 GROUP BYCOUNT 操作,并将输出作为单个 JSON.

考虑 Postgres 数据库中的以下 table:

Name Author Publisher Language
Book1 Jason Penguin English
Book2 Jason Macmillan English
Book3 Paul Macmillan English
Book4 Julia Macmillan English
Book5 Julia Penguin English

这是我当前的 SQL 查询

WITH first_selection AS (
    SELECT *
    FROM books
    where language='English')
SELECT json_build_object('author_options', json_agg(DISTINCT(author)),
                         'publisher_options', json_agg(DISTINCT(publisher)))
FROM first_selection

为此我得到了这个输出:

{
    "author_options":["Jason","Paul","Julia"],
    "publisher_options":["Penguin,"Macmillan"]
}

问题是我还需要每个出版商的图书数量,但我一直收到错误消息,指出不允许嵌套聚合。

我需要 JSON 输出中的图书数量。不一定在任何特定结构中,但信息需要存在。基本上我想要一个看起来像这样的输出:

{
    "author_options":["Jason","Paul","Julia"],
    "publisher_options":["Penguin,"Macmillan"],
    "publisher_details": {
                             "Penguin": 2,
                             "Macmillan": 3
                          }
}

如何计算每个出版商的图书数量并将结果放入 JSON?

 create table books (Name varchar(50), Author varchar(50), Publisher varchar(50), Language varchar(50));
 
 insert into books values('Book1',  'Jason',    'Penguin',      'English');
 insert into books values('Book2',  'Jason',    'Macmillan',    'English');
 insert into books values('Book3',  'Paul',     'Macmillan',    'English');
 insert into books values('Book4',  'Julia',    'Macmillan',    'English');
 insert into books values('Book5',  'Julia',    'Penguin',      'English');

查询:

 WITH first_selection AS (
     SELECT *
     FROM books
     where language='English')
 , publisherscount as
 (
 select Publisher, count(*) pcount
 from books
 group by publisher
 )
 SELECT json_build_object('author_options', json_agg(DISTINCT author),
                          'publisher_options', json_agg(DISTINCT publisher),
                          'publisher_details',(select   array_to_json(array_agg(json_build_object(publisher,pcount)))
                          from publisherscount)
                         )
 FROM first_selection

输出:

json_build_object
{author_options : [Jason, Julia, Paul], publisher_options : [Macmillan, Penguin], publisher_details : [{Macmillan : 3},{Penguin : 2}]}

dbhere

您可以在单独的步骤中汇总发布商,然后将其包含在最终结果中:

with first_selection as (
  select *
  from books
  where language = 'English'
), pub_info as (
  select json_object_agg(publisher, cnt) as details
  from (
    select publisher, count(*) as cnt
    from first_selection
    group by publisher
  ) t
)
SELECT json_build_object('author_options', json_agg(distinct author),
                         'publisher_options', json_agg(distinct publisher),
                         'publisher_details', (select details from pub_info))
FROM first_selection

Online example