Bar*_*dia 0 sql postgresql psql ltree
我有一个示例 Ltree 结构,我想将其作为 JSON 结构返回。我尝试过搜索堆栈溢出,但结果给出了错误的响应。
create table node
(
id integer not null,
name varchar(255),
path ltree not null
);
Run Code Online (Sandbox Code Playgroud)
我有这些数据
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');
Run Code Online (Sandbox Code Playgroud)
这就是我想通过查询收集的内容
[
{
"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": []
}
]
}
]
}
]
Run Code Online (Sandbox Code Playgroud)
我尝试过recursive with ..,但它一直循环而没有返回正确的值。
您需要两个部分,递归部分和另外一个函数。我已经在这里、这里和这里对此进行了解释,所以请查看那里以获取进一步的解释。
递归
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
Run Code Online (Sandbox Code Playgroud)
功能
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;
Run Code Online (Sandbox Code Playgroud)
请注意:对于此用例,ltree 结构并不是一个很好的选择,因为您需要一次又一次地计算子路径。对父级的简单引用会更有帮助且更快。
编辑: db<>fiddle 管理员很棒并且安装了 ltree 扩展,所以有一个新的 fiddle