Postgresql:如何将关系表分组为 Json 对象

Posted

技术标签:

【中文标题】Postgresql:如何将关系表分组为 Json 对象【英文标题】:Postgresql: How to GROUP BY as relational tables as Json Object 【发布时间】:2022-01-24 06:03:36 【问题描述】:

我有三个名为 UserPostCategory 的表,它们的数据如下:

用户表

 id | first_name | second_name 
  1     John          Doe
  2     Ellis         Mount               

帖子表

 id |   topic        |    body        |   author_id    |  category_id 
  1    Internet       ...some text          1                 1
  2    Web 3.0        ...some text          2                 1
  3    Consumer risk  ...some text          1                 2

分类表

 id |   type 
  1    Business     
  2    Technology         

所以我的问题是如何将postscategory_id 与其中的author 用户分组为json/object。 例如...这就是我希望获取数据的方式。

[
   technology: [
      
        id:1,
        topic: Internet,
        body: ...some text, 
        category_id: 1,
        author_id: 1
        author: 
          first_name: John,
          last_name: Doe
        
     ,
      
        id: 2,
        topic: Web 3.0,
        body: ...some text,
        category_id: 1, 
        author_id: 2
        author: 
          first_name: Ellis,
          last_name: Mount
        
     
   ],
   Business: [
      
        id:3,
        topic: Consumer risk,
        body: ...some text,
        category_id: 2, 
        author_id: 1,
        author: 
          first_name: John,
          last_name: Doe
        
      ,
    ],

]

所以,为了达到这个目的,我尝试使用 `join:

SELECT
    topic,
    body,
    category_id,
    json_build_object('first_name', max(first_name), 'second_name', max(second_name)) AS author,
FROM
    Post p
    JOIN User u ON p.author_id = u.id
GROUP BY
    category_id;  

不幸的是,这没有获取我想要的数据......所以如果有人知道如何查询这个,请在​​这里帮助我!

【问题讨论】:

【参考方案1】:

“编织”JSON 结构有点复杂。我希望它易于阅读。

select jsonb_object_agg(category, j)
from
(
 select category, jsonb_agg(to_jsonb(t) - 'category') j 
 from
 (
  select c."type" category, p.id, p.topic, p.body, p.category_id, p.author_id,
     jsonb_build_object('first_name',u.first_name,'second_name',u.second_name) author
  from posts p
  join category c on p.category_id = c.id
  join users u on p.author_id = u.id
 ) t 
 group by category
) t;

DB Fiddle

【讨论】:

这成功了,谢谢。【参考方案2】:

这可以使用嵌套子查询来完成,如下所示:

SELECT json_object_agg(type, C)
FROM (
SELECT type,
      (SELECT jsonb_agg(Category)
       FROM (SELECT id, topic, body, category_id, author_id,
                    (SELECT to_jsonb(Users)
                     FROM (SELECT first_name, second_name
                           FROM Users
                           WHERE id = Posts.author_id
                    ) AS Users) As author
            FROM Posts
            WHERE category_id=Category.id) As Category) As C
FROM Category 
ORDER BY type) As T

输出:


  "Business": [
    
      "id": 1,
      "body": "...some text",
      "topic": "Internet",
      "author": 
        "first_name": "John",
        "second_name": "Doe"
      ,
      "author_id": 1,
      "category_id": 1
    ,
    
      "id": 2,
      "body": "...some text",
      "topic": "Web 3.0",
      "author": 
        "first_name": "Ellis",
        "second_name": "Mount"
      ,
      "author_id": 2,
      "category_id": 1
    
  ],
  "Technology": [
    
      "id": 3,
      "body": "...some text",
      "topic": "Consumer risk",
      "author": 
        "first_name": "John",
        "second_name": "Doe"
      ,
      "author_id": 1,
      "category_id": 2
    
  ]

【讨论】:

这也行得通,谢谢。

以上是关于Postgresql:如何将关系表分组为 Json 对象的主要内容,如果未能解决你的问题,请参考以下文章

将嵌套的 JSON 从 PostgreSQL 的多对多连接表返回到 node.js

如何获得 PostgreSQL 中的两个平均值之间的差异,平均值在列上,最终表按两列分组?

Postgresql:如何在不使用中间 hstore 的情况下将键值表转换为 json

将 JSON 字符串数组设置为 PostgreSQL 表中的列

如何在 PostgreSQL 中获取表的每一天的第一个日期并将其转换为 JSON

如何使用 Hibernate 和 postgresql 为一对多关系实现每个表的自动递增 id 字段