postgresql 如何在多对多关系中加载和分组相关记录

zpgglvta  于 2023-06-29  发布在  PostgreSQL
关注(0)|答案(1)|浏览(111)

我正在与一个不寻常的情况下加载数据在许多太多的关系(PostgreSQL)。我不知道我是否对数据结构有一些错误的假设,或者我的SQL知识不够好,但不知何故,我找不到解决方案。
我有一个非常简单的数据结构:

项目

item_id | group_id | item_name

标签

tag_id | tag_name

每个项目可以有许多标签,并且每个标签可以分配给许多项目。项目可以按group_id进行分组。
SQL表符合预期:

items
tags
tags_items - many to many connection table with tag_id | item_id columns.

现在,我想将此数据作为一组项目加载,按group_id聚合,大致如下所示:

[
  {
     group_id,
     items: [
        {
            item_id,
            item_name,
            tags: [ related_tag_1, related_tag_2 ]
        }
     //...
     ]
   },
   //...
]

因此,我想按group_id对项目进行分组,以便单个记录包含分配给该组的项目数组,并且每个项目包含按多对多关系分配给该项目的标记数组。
我尝试过不同的方法,但我很难在不放置几个嵌套SQL查询的情况下实现它。你有什么建议是最好的方式,也是明智的性能,创造这样的结构?不必完全相同,但聚合方面很重要。
我最好的东西是这个:

SELECT 
    group_id,
    json_agg(json_build_object(
        'item_id', items.item_id,
        'item_name', items.item_name,
        'tags', array(
            SELECT json_build_object('id', tag_id, 'label', tag_name) FROM tags_items LEFT JOIN tags ON tags_items.tag_id = tags.id  WHERE item_id = items.id
        )
    )) as items 
FROM 
    items
GROUP BY 
    responses.group_id

它可以工作,但是很难处理这个查询,例如通过标签添加过滤器等。有没有更好的办法

bbuxkriu

bbuxkriu1#

如果没有模式或测试数据,我无法运行它来验证它是否运行没有错误,但您可能能够通过使用子查询(或者使用CTE,如果对您来说更易读)接近您要查找的内容。这允许您在为单个项目聚合标记之后过滤标记,然后再将项目聚合到每组的项目列表中。这可能类似于:

SELECT group_id, json_build_object( 'items', json_agg(item_json) )
FROM (
  SELECT group_id, item_id, json_build_object( 'item_id', items.item_id,
        'item_name', items.item_name,
        'tags', json_agg(
            json_build_object('id', ti.tag_id, 'label', ti.tag_name) 
        ) as item_json
  FROM items i LEFT JOIN tags_items ti on ti.item_id = i.id LEFT JOIN tags t on t.id = ti.tag_id
  GROUP BY group_id, item_id, item_name
  -- filter on aggregate in having clause to remove items that don't have a specific tag in their array of tag names
  HAVING 'healthy' = ANY( array_agg(ti.tag_name) )
 ) item_aggregate
--could also filter in this WHERE clause
WHERE true
group by group_id

相关问题