【问题标题】:Recursively generate JSON tree from hierarchical table in Postgres and jOOQ从 Postgres 和 jOOQ 中的分层表递归生成 JSON 树
【发布时间】:2021-06-13 18:47:13
【问题描述】:

我在 Postgres 数据库中有一个分层表,例如category。结构简单如下:

id parent_id name
1 null A
2 null B
3 1 A1
4 3 A1a
5 3 A1b
6 2 B1
7 2 B2

我需要从这张表中得到这样的递归深度树结构:

[
  {
    "id": 1,
    "name": "A",
    "children": [
      {
        "id": 3,
        "name": "A1",
        "children": [
          {
            "id": 4,
            "name": "A1a",
            "children": []
          },
          {
            "id": 5,
            "name": "A1b",
            "children": []
          }
        ]
      }
    ]
  },
  {
    "id": 2,
    "name": "B",
    "children": [
      {
        "id": 6,
        "name": "B1",
        "children": []
      },
      {
        "id": 7,
        "name": "B2",
        "children": []
      }
    ]
  },
]

是否有可能使用WITH RECURSIVEjson_build_array() 的组合或其他一些解决方案的未知深度?

【问题讨论】:

    标签: json postgresql jooq


    【解决方案1】:

    我在this excellent blog post here 中找到了这个问题的答案,因为我想知道如何在 jOOQ 中概括这个问题。如果 jOOQ 可以以通用方式实现任意递归对象树,那将很有用:https://github.com/jOOQ/jOOQ/issues/12341

    同时,使用受上述博客文章启发的 SQL 语句,并进行了一些修改。如果必须,请转换为 jOOQ,尽管您也可以将其存储为视图:

    WITH RECURSIVE
      d1 (id, parent_id, name) as (
        values
          (1, null, 'A'),
          (2, null, 'B'),
          (3,    1, 'A1'),
          (4,    3, 'A1a'),
          (5,    3, 'A1b'),
          (6,    2, 'B1'),
          (7,    2, 'B2')
      ),
      d2 AS (
        SELECT d1.*, 0 AS level
        FROM d1
        WHERE parent_id IS NULL
        UNION ALL
        SELECT d1.*, d2.level + 1
        FROM d1
        JOIN d2 ON d2.id = d1.parent_id
      ),
      d3 AS (
        SELECT d2.*, jsonb_build_array() children
        FROM d2
        WHERE level = (SELECT max(level) FROM d2)
        UNION (
          SELECT (branch_parent).*, jsonb_agg(branch_child)
          FROM (
            SELECT 
              branch_parent, 
              to_jsonb(branch_child) - 'level' - 'parent_id' AS branch_child
            FROM d2 branch_parent
            JOIN d3 branch_child ON branch_child.parent_id = branch_parent.id
          ) branch
          GROUP BY branch.branch_parent
          UNION
          SELECT d2.*, jsonb_build_array()
          FROM d2
          WHERE d2.id NOT IN (
            SELECT parent_id FROM d2 WHERE parent_id IS NOT NULL
          )
        )
      )
    SELECT jsonb_pretty(jsonb_agg(to_jsonb(d3) - 'level' - 'parent_id')) AS tree
    FROM d3
    WHERE level = 0;
    

    dbfiddle。再次阅读linked blog post,了解其工作原理

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-08-04
      • 1970-01-01
      • 2011-12-28
      • 1970-01-01
      • 2022-10-06
      • 1970-01-01
      • 2016-04-25
      • 2013-06-05
      相关资源
      最近更新 更多