json_agg()中的重复行在查询中有2个横向连接

时间:2018-04-27 19:22:47

标签: json postgresql aggregate-functions

在查询上执行横向连接时,我得到一个奇怪的结果

我有以下表结构

task->id 
comment -> id , taskId, comment
tasklink -> taskId, type, userid

单个任务记录(id 10),1个评论记录(“row1”,“测试评论”)和5个tasklink记录(全部带有taskid 10)

我期待这个查询

select task.id,
       json_agg(json_build_object('id',c.id, 'user',c.comment)) as comments,
       json_agg(json_build_object('type',b.type, 'user',b.userid)) as users

  FROM task 
  left join lateral (select c.* from comment c where task.id = c.taskid) c on true
  left join lateral (select b.* from taskuserlink b where task.id = b.taskid) b on true

  where task.id = 10    
  GROUP BY task.id ;

返回

id | comments                                   | users
---------------------------------------------------------------------
10  "[{"id":"row1","user":"a test comment"}]"   "[{"type":"updatedBy","user":1},"type":"closedBy","user":5},"type":"updatedBy","user":5},"type":"createdBy","user":5},{"type":"ownedBy","user":5}]"

相反,我得到了这个

id | comments                                                                                                                                                                                           | users
10  "[{"id":"row1","user":"a test comment"},{"id":"row1","user":"a test comment"},{"id":"row1","user":"a test comment"},{"id":"row1","user":"a test comment"},{"id":"row1","user":"a test comment"}]"   "[{"type":"updatedBy","user":1},{"type":"closedBy","user":5},{"type":"updatedBy","user":5},{"type":"createdBy","user":5},{"type":"ownedBy","user":5}]"

即,对于每个link行,comment行都是重复的

我在想我错过了一些非常明显的东西,但由于我刚刚开始使用Postgres(和sql),我有点难过

我希望得到一些关于我出错的指导

1 个答案:

答案 0 :(得分:1)

将聚合移动到子查询中:

select id, comments, users
from task t
left join lateral (
    select json_agg(json_build_object('id',c.id, 'user',c.comment)) as comments
    from comment c
    where t.id = c.taskid
    ) c on true
left join lateral (
    select json_agg(json_build_object('type',b.type, 'user',b.userid)) as users
    from taskuserlink b 
    where t.id = b.taskid 
    ) b on true

DbFiddle.