PostgreSQL将数据聚合到单行

时间:2018-09-11 14:23:24

标签: sql postgresql join

使用以下SQL查询,我想基于posts.liked_by数组添加一个包含来自另一个表的数据的JSON对象数组:

SELECT 
  p.id, 
  p.author, 
  p.content, 
  u2.id, 
  u2.username, 
  p.liked_by AS likedby
FROM posts p
INNER JOIN users u1 
    ON p.author = u1.id
LEFT JOIN users u2 
    ON u2.id = ANY(p.liked_by)

我得到了预期的输出

╔════╤════════╤═════════════╤══════════╤═════════╗
║ id │ author │ content     │ username │ likedby ║
╠════╪════════╪═════════════╪══════════╪═════════╣
║ 1  │ 1      │ Lorem Ipsum │ John Doe │ {1, 2}  ║
╚════╧════════╧═════════════╧══════════╧═════════╝

现在,我想将likedby列修改为包含用户数据的对象数组,以符合以下要求:

+----+--------+-------------+----------+-----------------------------------------------------------------+
| id | author | content     | username | liked_by                                                        |
+----+--------+-------------+----------+-----------------------------------------------------------------+
| 1  | 1      | Lorem Ipsum | John Doe | [{id: 1, username: "John Doe"}, {id: 2, username: "Sam Smith"}] |
+----+--------+-------------+----------+-----------------------------------------------------------------+

posts表的数据的结构类似于

+----+--------+-------------+-----------+-----------+
| id | author | content     | author_id | liked_by  |
+----+--------+-------------+-----------+-----------+
| 1  | 1      | lorem ipsum | 1         | {1, 2, 3} |
+----+--------+-------------+-----------+-----------+

,用户表的结构为

+----+----------+
| id | username |
+----+----------+
| 1  | John Doe |
+----+----------+

我该怎么做?

2 个答案:

答案 0 :(得分:2)

它与显式联接一起工作(顺便说一下,这不是混合和匹配的好形式):

SELECT
    ...
FROM posts p
INNER JOIN users u1 
    ON p.author = u1.id
LEFT JOIN users u2 
    ON u2.id = ANY(p.liked_by)

原因,从postgres documentation

  

... JOIN的绑定比逗号更紧密。例如FROM T1 CROSS JOIN   T2 INNER JOIN T3 ON条件不同于FROM T1,T2 INNER   JOIN T3 ON条件,因为该条件可以在   第一种情况,但不是第二种情况。

答案 1 :(得分:2)

要获取liked_by列的汇总用户名,可以将子查询与jsonb_agg()jsonb_build_object()函数一起使用:

SELECT posts.*, "user".username as author_name,  
    (SELECT jsonb_agg(jsonb_build_object("user".id, "user".username)) FROM "user" where "user".id = any(posts.liked_by)  )
FROM posts
INNER JOIN "user"
ON posts.author_id = "user".id

http://rextester.com/KMEY13984