Sql Postgres-多级父子关系数据
我们的亲子关系如下Sql Postgres-多级父子关系数据,sql,postgresql,performance,parent-child,hierarchical-data,Sql,Postgresql,Performance,Parent Child,Hierarchical Data,我们的亲子关系如下 create table dependency ( packageid int, dependant_packageid int); insert into dependency values (2,1); insert into dependency values (3,1); insert into dependency values (4,1); insert into dependency values (5,2); insert into dependency va
create table dependency ( packageid int, dependant_packageid int);
insert into dependency values (2,1);
insert into dependency values (3,1);
insert into dependency values (4,1);
insert into dependency values (5,2);
insert into dependency values (6,3);
insert into dependency values (7,4);
insert into dependency values (7,5);
insert into dependency values (8,5);
insert into dependency values (8,3);
insert into dependency values (4,5);
insert into dependency values (6,4);
insert into dependency values (5,3);
生成表的脚本,如下所示
create table dependency ( packageid int, dependant_packageid int);
insert into dependency values (2,1);
insert into dependency values (3,1);
insert into dependency values (4,1);
insert into dependency values (5,2);
insert into dependency values (6,3);
insert into dependency values (7,4);
insert into dependency values (7,5);
insert into dependency values (8,5);
insert into dependency values (8,3);
insert into dependency values (4,5);
insert into dependency values (6,4);
insert into dependency values (5,3);
我们希望根据下面提到的查询获取数据
非常感谢您的帮助…愉快的编码…)这里是一个递归查询的快速示例,可以为每个id显示不同的完整依赖项列表:
WITH RECURSIVE rcte AS (
--Recursive Seed
SELECT packageid as initialid,
packageid,
dependant_packageid,
CAST(packageid || ',' || dependant_packageid as varchar(30)) as path,
1 as depth
FROM dependency
UNION ALL
--Recursive Term
SELECT initialid,
dependency.packageid,
dependency.dependant_packageid,
CAST(rcte.path || ',' || dependency.dependant_packageid as varchar(30)),
rcte.depth + 1
FROM rcte
INNER JOIN dependency ON rcte.dependant_packageid = dependency.packageid
)
SELECT r1.initialid as packageid, path as dependant_packages
FROM rcte r1
LEFT OUTER JOIN rcte r2
ON r2.path LIKE r1.path || '%' AND r1.depth < r2.depth
WHERE r2.initialid IS NULL
ORDER BY r1.path;
以递归rcte为例(
--递归种子
选择packageid作为初始ID,
包装,
依亲包裹,
将(packageid | |','| | dependent | u packageid转换为varchar(30))作为路径,
1作为深度
从依赖
联合所有
--递归项
选择initialid,
dependency.packageid,
dependency.dependency_packageid,
强制转换(rcte.path | |','| | dependency.dependent_packageid为varchar(30)),
rcte深度+1
来自rcte
rcte.dependent_packageid上的内部联接依赖项=dependency.packageid
)
选择r1.initialid作为packageid,路径作为Dependent\u包
来自rcte r1
左外连接rcte r2
在r2.path上,如r1.path | |“%”和r1.depth
递归CTE有两部分。递归种子
运行一次。它从表中收集记录,这些记录最初将被送入第二部分,即递归项
,该项将迭代直到其联接失败。在该递归术语中,我们将CTErcte
连接回表中,并将CTE的从属包ID
连接到表的包ID
最后,SELECT
语句引用来自CTE和自连接的那些结果,以从所有这些迭代中找到最长的不同路径
使用相同的递归逻辑,您可以获得剩余的记录集 我建议在表中添加主键:
create table dependency (serial id, packageid int, dependant_packageid int);
然后,要获得层次结构,可以使用如下查询:
WITH RECURSIVE rcte AS (
SELECT id,
packageid AS initial_packageid,
dependant_packageid,
ARRAY[dependant_packageid::text]::text[] as path,
1 as depth
FROM dependency
UNION ALL
SELECT rcte.id,
rcte.initial_packageid,
dependency.dependant_packageid,
rcte.path || dependency.dependant_packageid::text,
rcte.depth + 1
FROM rcte
JOIN dependency ON rcte.dependant_packageid = dependency.packageid ),
cte_hierarchy AS (
SELECT initial_packageid AS packageid,
(ARRAY_AGG( '(' || ARRAY_TO_STRING(path, ',') || ')' ORDER BY depth DESC))[1] AS hierarchy
FROM rcte
GROUP BY id, initial_packageid )
SELECT packageid, STRING_AGG(hierarchy, ',')
FROM cte_hierarchy
GROUP BY packageid
ORDER BY packageid
要获取父包,只需使用:
SELECT dependant_packageid AS packageid, ARRAY_AGG(DISTINCT packageid)
FROM dependency
GROUP BY dependant_packageid
ORDER BY dependant_packageid
您的模式适合于此。这里需要的是递归CTE。这是一个CTE内部的两部分查询,它会迭代地连接回自身,直到连接失败。
SELECT dependant_packageid AS packageid, ARRAY_AGG(DISTINCT packageid)
FROM dependency
GROUP BY dependant_packageid
ORDER BY dependant_packageid