【问题标题】:Nesting PostgreSQL relational query results as JSON objects将 PostgreSQL 关系查询结果嵌套为 JSON 对象
【发布时间】:2020-05-02 12:10:07
【问题描述】:

我的数据库中有 3 个表:parentchildrengrandchildren。由于parent-childrenchildren-grandchildren是多对多相关的,所以也有2个关系表。

我有一个查询,我希望将所有 parent 元素与嵌套的 childrengrandchildren 行(如果有)作为 JSON 对象:

SELECT
  p.*,
  COALESCE(json_agg(json_build_object(
    'child_id', c.child_id,
    'child_name', c.child_name
    -- * GET ALL grandchildren FOR THIS child HERE!
  )) FILTER (WHERE c.child_id IS NOT NULL), '[]')
  AS children
FROM parent p
LEFT JOIN parent_children pc
ON pc.parent_id = p.parent_id
LEFT JOIN children c
ON c.child_id = pc.child_id
GROUP BY p.parent_id;

这个查询,后来在我的 JS 代码中,最终成为一个不错的 JSON 对象:

[
  {
    "parent_id": 1,
    "parent_name": "whatever",
    "children": [
      {
        "child_id": 1,
        "child_name": "le child"
      },
      {
        "child_id": 2,
        "child_name": "le second child"
      }
    ]
  },
  {
    "parent_id": 2,
    "parent_name": "second",
    "children": []
  }
]

正如我在查询中所评论的,我想为每个 children 元素添加所有 grandchildren 行。我有一个与上面相同的查询,除了它使用不同的表来获取该关系:

SELECT
  c.*,
  COALESCE(json_agg(json_build_object(
    'grandchild_id', gc.grandchild_id,
    'grandchild_name', gc.grandchild_name
  )) FILTER (WHERE gc.grandchild_id IS NOT NULL), '[]')
  AS grandchildren
FROM children c
LEFT JOIN children_grandchildren cg
ON cg.child_id = c.child_id
LEFT JOIN grandchildren g
ON g.grandchild_id = gc.grandchild_id
GROUP BY c.child_id;

我不确定这是否可能,如果可以,如何精确嵌套查询以获得如下结果:

[
  {
    "parent_id": 1,
    "parent_column": "whatever",
    "children": [
      {
        "child_id": 1,
        "child_name": "le child",
        "grandchildren": [
          {
            "grandchild_id": 1,
            "grandchild_name": "foo"
          },
          {
            "grandchild_id": 2,
            "grandchild_name": "bar"
          }
        ]
      },
      {
        "child_id": 2,
        "child_name": "le second child",
        "grandchildren": []
      }
    ]
  },
  {
    "parent_id": 2,
    "parent_name": "second",
    "children": []
  }
]

【问题讨论】:

    标签: json postgresql nested aggregate


    【解决方案1】:

    我设法通过简单地LEFT JOINing grandchildren 表解决了这个问题:

    SELECT
      p.*,
      COALESCE(json_agg(json_build_object(
        'child_id', c.child_id,
        'child_name', c.child_name
        -- * GET ALL grandchildren FOR THIS child HERE!
      )) FILTER (WHERE c.child_id IS NOT NULL), '[]')
      AS children
    FROM parent p
    LEFT JOIN parent_children pc
    ON pc.parent_id = p.parent_id
    LEFT JOIN children c
    ON c.child_id = pc.child_id
    LEFT JOIN (
      SELECT
        c.*,
        COALESCE(json_agg(json_build_object(
          'grandchild_id', g.grandchild_id,
          'grandchild_name', g.grandchild_name
        ))
        FILTER (WHERE g.grandchild_id IS NOT NULL), '[]') 
        AS grandchildren
      FROM children c
      LEFT JOIN children_grandchildren cg
      ON c.child_id = cg.child_id
      LEFT JOIN grandchildren g
      ON g.grandchild_id = cg.grandchild_id
      GROUP BY c.child_id
    ) grandchildren ON grandchildren.child_id = c.child_id
    GROUP BY p.parent_id;
    
    

    这会生成具有我需要的关系的 JSON 对象:

    [
      {
        "parent_id": 1,
        "parent_column": "whatever",
        "children": [
          {
            "child_id": 1,
            "child_name": "le child",
            "grandchildren": [
              {
                "grandchild_id": 1,
                "grandchild_name": "foo"
              },
              {
                "grandchild_id": 2,
                "grandchild_name": "bar"
              }
            ]
          },
          {
            "child_id": 2,
            "child_name": "le second child",
            "grandchildren": []
          }
        ]
      },
      {
        "parent_id": 2,
        "parent_name": "second",
        "children": []
      }
    ]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-09-16
      • 2016-03-22
      • 1970-01-01
      • 2013-03-18
      • 1970-01-01
      • 2021-12-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多