Postgres LTREE 按 parents 和 children 分组显示
Postgres LTREE display by grouping parents and children
我有一个示例 Ltree 结构,我想 return 它作为 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 ..
但它一直在循环,但没有 return 正确的值。
您需要两部分,递归部分和函数。我已经对此进行了解释 , and ,所以请查看那里以获得进一步的解释。
递归
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
我有一个示例 Ltree 结构,我想 return 它作为 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 ..
但它一直在循环,但没有 return 正确的值。
您需要两部分,递归部分和函数。我已经对此进行了解释
递归
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