复杂连接上的重复数组

时间:2016-08-20 13:03:30

标签: postgresql aggregate-functions

我想在postgresql db中创建复杂结构的非规范化视图。我有一个主要实体games和一些一对多关系,例如tags(两种类型)和files。问题是数组包含重复id的项,而不管子查询中的distinct子句。我将查询缩小到相关部分:

select
  array_to_json(array_remove(array_agg((
    select distinct t.id where t.type = 1
  )), null))::jsonb as genre_ids
from games g
left outer join game_tags gt on gt.game_id = g.id -- one-to-many
left outer join tags t on gt.tag_id = t.id
left outer join game_files gf on gf.game_id = g.id -- one-to-many as well
left outer join files f on gf.file_id = f.id
left outer join ratings r on r.game_id = g.id
group by g.id;

假设我有id=1和关系

的游戏
# game_tags (game_id, tag_id)
1, 100

# game_files (game_id, file_id)
1, 1000
1, 1001
1, 1002
1, 1003

然后在查询结果中我会看到数组[100, 100, 100, 100]。标签数量大于1时的情况相同。我不知道这是因为错误的聚合部分还是因为错误的分组。我希望distinct关键字可以解决问题,但事实并非如此。当然我可以在将项目发送到前端之前对其进行过滤,但我认为这是一种错误的方式。

我坚持第9.5页。

1 个答案:

答案 0 :(得分:1)

你遇到的问题是你需要在不同的基础上进行分组:一次用于游戏标签,一次用于文件。您可以通过子查询作为行源来解决此问题。分组发生在子查询中,因此它们不会相互影响:

select g.*, t.genre_ids, f.file_ids
from games g
left join (
  select gt.game_id, jsonb_agg(t.id) as genre_ids
  from game_tags gt
  join tags t on gt.tag_id = t.id
  where t."type" = 1
  group by gt.game_id) t on t.game_id = g.id
left join (
  select game_id, jsonb_agg(file_id) as file_ids
  from game_files
  group by game_id) f on f.game_id = g.id
left join ratings r on r.game_id = g.id -- not used
;