我有一个示例Ltree结构,而不想将其作为JSON结构返回。 我尝试过搜索堆栈溢出,但是结果给出了错误的响应。
create table node
(
id integer not null,
name varchar(255),
path ltree not null
);
我有这些数据
INSERT INTO node (id,name,path) VALUES (1,'Residential','1');
INSERT INTO node (id,name,path) VALUES (2,'Commercial','2');
INSERT INTO node (id,name,path) VALUES (3,'Industrial','3');
INSERT INTO node (id,name,path) VALUES (4,'Res type 1','1.4');
INSERT INTO node (id,name,path) VALUES (5,'Comm type 1','2.5');
INSERT INTO node (id,name,path) VALUES (6,'Industrial 1','3.6');
INSERT INTO node (id,name,path) VALUES (7,'Residential 2','1.4.7');
INSERT INTO node (id,name,path) VALUES (8,'Commercial 2','2.5.8');
INSERT INTO node (id,name,path) VALUES (9,'Industrial 2','3.6.9');
这就是我要通过查询收集的信息
[
{
"name": "Residentioal",
"children": [
{
"name": "Res type 1",
"children": [
{
"name": "Residential 2",
"children": []
}
]
}
]
},
{
"name": "Commercial",
"children": [
{
"name": "Comm type 1",
"children": [
{
"name": "Commercial 2",
"children": []
}
]
}
]
},
{
"name": "Industrial",
"children": [
{
"name": "Industrial 1",
"children": [
{
"name": "Industrial 2",
"children": []
}
]
}
]
}
]
我尝试了recursive with ..
,但是它一直循环执行而没有返回正确的值。
答案 0 :(得分:1)
您需要两个部分,一个是递归部分,另一个是函数。我已经对此here,here和here进行了解释,因此请查看那里以获取进一步的解释。
递归
WITH RECURSIVE cte AS (
SELECT
id,
name,
path,
json_build_object('name', name, 'children', ARRAY[]::text[]) AS jsonobject,
ARRAY[]::text[] || (row_number() OVER () - 1)::text as jsonpath,
0 as depth
FROM node
WHERE path = subpath(path, 0, 1) --parents
UNION ALL
SELECT
n.id,
n.name,
n.path,
json_build_object('name', n.name, 'children', ARRAY[]::text[]),
jsonpath || '{children}' || (row_number() OVER (PARTITION BY subpath(n.path, depth, 1)::text ORDER BY subpath(n.path, depth + 1, 1)::text::int) - 1)::text,
c.depth + 1
FROM
node n
JOIN cte c
ON c.id = subpath(n.path, depth, 1)::text::int
AND nlevel(n.path) = depth + 2 AND subpath(n.path, depth + 1, 1)::text::int = n.id
)
SELECT * FROM cte
功能
CREATE OR REPLACE FUNCTION nested_json() RETURNS jsonb AS $$
DECLARE
_json_output jsonb;
_temprow record;
BEGIN
_json_output := '[]'::jsonb;
FOR _temprow IN
-- <Add the CTE from above here>
LOOP
SELECT
jsonb_insert(
_json_output,
_temprow.jsonpath,
_temprow.jsonobject
)
INTO _json_output;
END LOOP;
RETURN _json_output;
END;
$$ LANGUAGE plpgsql;
请注意:对于这种用例,ltree结构并不是一个很好的选择,因为您需要一次又一次地计算子路径。对父母的简单引用会更有用和更快。
编辑:db <> fiddle管理员非常棒,并安装了ltree扩展名,因此有一个新的fiddle