gpt4 book ai didi

json - 在 Postgres 中将邻接列表作为嵌套 JSON 返回

转载 作者:行者123 更新时间:2023-11-29 12:10:38 25 4
gpt4 key购买 nike

给定两列 Postgres 表 (id, parent_id) 的最简单基本情况,是否有一种方法可以查询 id 并将所有子项作为嵌套的 json 结构返回,如下所示?

{
"id": 1,
"children": [{
"id": 2,
"children": [{
"id": 3,
"children": []
}]
}]
}

我了解如何通过表进行递归,但我无法拼凑出如何使用任何 psql json 函数来返回如上所示的结果。也许我应该只使用我选择的语言在后处理中进行转换?

SQLFiddle目前的进展。

最佳答案

太难了,我花了好几个小时才解决:-P

CREATE TABLE foo (
id INT PRIMARY KEY,
parent_id INT);

insert into foo values (1, null);
insert into foo values (2, 1);
insert into foo values (3, 2);

WITH RECURSIVE
tree AS (
SELECT 1 AS round, id, parent_id, ARRAY(SELECT id FROM foo WHERE parent_id = f.id) AS children
FROM foo f
WHERE id = 1
UNION ALL
SELECT round+1, f.id, f.parent_id, ARRAY(SELECT id FROM foo WHERE parent_id = f.id) AS children
FROM tree t
JOIN foo f ON (f.id = ANY(t.children))
),
rev AS (
SELECT r.round-1 AS round,
to_jsonb(ARRAY(
SELECT a
FROM (
SELECT f.parent_id AS id, json_agg(jsonb_build_object('id', f.id, 'children', '{}'::text[])) AS children
FROM tree t
JOIN foo f ON (f.id = t.id)
WHERE t.round = r.round
GROUP BY f.parent_id
) a
)) AS list
FROM (SELECT MAX(round)::int AS round FROM tree) r
UNION ALL
SELECT r.round-1,
to_jsonb(ARRAY(
SELECT a
FROM (
SELECT f.parent_id AS id, json_agg(jsonb_build_object('id', f.id, 'children', t->'children')) AS children
FROM jsonb_array_elements(list) t
JOIN foo f ON (f.id = (t->>'id')::int)
GROUP BY f.parent_id
) a
)) AS list
FROM rev r
WHERE round > 1
)
SELECT list as nested_json_tree
FROM rev
WHERE round = 1

复杂性在于需要先构建树(自上而下),然后从树自下而上构建对象。由于递归查询的限制,递归自下而上是棘手的,例如 UNION ALL 部分中的递归别名不能被分组,也不能包含在子查询中。我通过反向循环展开来解决这个问题。

这个查询应该正确地构建复杂的树,每个节点有多个子节点,以及任意数量的嵌套级别。

关于json - 在 Postgres 中将邻接列表作为嵌套 JSON 返回,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37646813/

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