gpt4 book ai didi

postgresql - 如何在树结构中合并 JSONB 字段?

转载 作者:行者123 更新时间:2023-11-29 12:04:59 24 4
gpt4 key购买 nike

我在 Postgres 中有一个存储树结构的表。每个节点都有一个jsonb字段:params_diff:

CREATE TABLE tree (id INT, parent_id INT, params_diff JSONB);
INSERT INTO tree VALUES
(1, NULL, '{ "some_key": "some value" }'::jsonb)
, (2, 1, '{ "some_key": "other value", "other_key": "smth" }'::jsonb)
, (3, 2, '{ "other_key": "smth else" }'::jsonb);

我需要的是通过 id 选择一个节点,该节点带有额外生成的 params 字段,该字段包含合并所有 params_diff 的结果整个父链:

SELECT tree.*, /* some magic here */ AS params FROM tree WHERE id = 3;

id | parent_id | params_diff | params
----+-----------+----------------------------+-------------------------------------------------------
3 | 2 | {"other_key": "smth else"} | {"some_key": "other value", "other_key": "smth else"}

最佳答案

通常,一个 recursive CTE可以胜任这项工作。示例:

我们只需要更多的魔法来分解、处理和重新组装 JSON 结果。我从你的例子中假设,你只需要每个键一次,搜索路径中的第一个值(自下而上):

WITH RECURSIVE cte AS (
SELECT id, parent_id, params_diff, 1 AS lvl
FROM tree
WHERE id = 3

UNION ALL
SELECT t.id, t.parent_id, t.params_diff, c.lvl + 1
FROM cte c
JOIN tree t ON t.id = c.parent_id
)
SELECT id, parent_id, params_diff
, (SELECT json_object(array_agg(key ORDER BY lvl)
, array_agg(value ORDER BY lvl))::jsonb
FROM (
SELECT key, value
FROM (
SELECT DISTINCT ON (key)
p.key, p.value, c.lvl
FROM cte c, jsonb_each_text(c.params_diff) p
ORDER BY p.key, c.lvl
) sub1
ORDER BY lvl
) sub2
) AS params

FROM cte
WHERE id = 3;

如何?

  1. 使用经典的递归 CTE 遍历树。
  2. 使用 jsonb_each_text() 创建一个包含所有键和值的派生表在LATERAL JOIN , 记住搜索路径中的级别 ( lvl )。
  3. 使用DISTINCT ON获得“第一”(最低 lvl )value对于每个 key .细节:
  4. 对生成的键和值进行排序和聚合,并将数组提供给 json_object() 构建最终的params值(value)。

SQL Fiddle (只有 pg 9.3 可以使用 json 而不是 jsonb )。

关于postgresql - 如何在树结构中合并 JSONB 字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28648100/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com