我有一个包含父/子关系的数据库,我试图折叠数据,以便子ID的所有父ID都在同一行。
Name | ID | Parent_ID
A 1 NULL
B 2 1
C 3 2
D 4 3
我正在尝试实现以下目标:
Name | ID | Top_Level | Sub_Level | Sub_Level_2
A 1 NULL
B 2 1
C 3 1 2
D 4 1 2 3
我玩了一些递归,但没有得到正确的结果,我不知道如何继续。任何提示将不胜感激!
with recursive stuff as (
select
*
from table
where
id = 4
union
select
table.*
from table
join stuff on stuff.parent_id = table.id
)
select * from stuff;
答案 0 :(得分:0)
不是很优雅,但我现在想不出任何不同的东西:
with recursive stuff (name, id, parent_id, nodes, level) as (
select name, id, parent_id, array[parent_id], 1 as level
from t
where id = 4
union
select c.name, c.id, c.parent_id, p.nodes||c.parent_id, p.level + 1
from t c
join stuff p on p.parent_id = c.id
), level_info as (
select max(level) as max_level
from stuff
), path_info as (
select nodes as all_nodes
from stuff
where level = (select max_level from level_info)
)
select stuff.name,
stuff.id,
stuff.level,
case
when level = max_level then null
else all_nodes[max_level - 1]
end as root,
case
when level < max_level - 1 then all_nodes[max_level - 2]
end as sub_level,
case
when level < max_level - 2 then all_nodes[max_level - 3]
end as sub_level_2
from stuff, path_info, level_info
order by id;
递归部分收集访问的每个节点的整个路径。然后我们需要计算最长路径和最高等级,以便能够找到最高等级和两个子等级。这就是其他两个CTE所做的事情。
我将它们交叉连接到基础CTE,以便能够访问那里的列。由于两个CTE只有一行,因此交叉连接不会更改结果,但可以更轻松地使用这些值。
尽管如此,这可能不是最有效的方式。