问题描述
我的桌子看起来像这样:
id | name | type_id | desc | parent_id
1 | Foo | 1 | Foo | NULL
2 | Bar | 2 | Bar | 1
3 | FB | 2 | FB | 1
4 | Foo1 | 1 | Foo1 | NULL
5 | Bar1 | 2 | Bar1 | 4
6 | FB1 | 2 | FB1 | 4
我想提供最低节点的ID,将所有数据返回到单行中的最高节点(还有其他数据与此一起返回)。 例如,我想提供ID 3,结果看起来像这样:
xxxxx (other data) | id | name | type_id | desc | parent_id | id | name | type_id | desc | parent_id
xxxxxxx | 3 | FB | 2 | FB | 1 | 1 | Foo | 1 | Foo | NULL
不幸的是,我没有找到任何适合我的东西。我有一个CTE,但是它自上而下,每个节点都是自己的行:
WITH RECURSIVE cte AS (
select T.*
from table as T
where T.id = 3
union all
select T.*
from table as T
inner join cte as C
on T.parent_id = C.id
)
SELECT * FROM cte
执行此操作时,我只会得到一个结果:
id | name | type_id | desc | parent_id
3 | FB | 2 | FB | 1
任何帮助将不胜感激,谢谢!
解决方法
公用表表达式的逻辑看起来不错;它为原始id
生成一行,然后为每个父级生成一行。要将结果行转换为列,然后可以使用条件聚合-这要求您事先确定最大级别数。对于两个级别,这将是:
with recursive cte as (
select t.*,1 lvl
from table as t
where t.id = 3
union all
select t.*,c.lvl + 1
from table as t
inner join cte as c on t.parent_id = c.id
)
select
max(id) filter(where lvl = 1) id,max(name) filter(where lvl = 1) name,max(type_id) filter(where lvl = 1) type_id,max(descr) filter(where lvl = 1) descr,max(parent_id) filter(where lvl = 1) parent_id,max(id) filter(where lvl = 2) id2,max(name) filter(where lvl = 2) name2,max(type_id) filter(where lvl = 2) type_id2,max(descr) filter(where lvl = 2) descr2,max(parent_id) filter(where lvl = 2) parent_id2,from cte
您可能还需要考虑将行累积为json对象的数组:
with recursive cte as (
select t.*,c.lvl + 1
from table as t
inner join cte as c on t.parent_id = c.id
)
select jsonb_agg(to_jsonb(c) order by lvl) res
from cte c
,
我已经使用Oracle 11g通过Pivot,Row_number和层次结构查询来解决此问题。
WITH CTE1 AS (SELECT A.*,LEVEL AS LVL FROM TABLE1 A
START WITH ID IN (2,3)
CONNECT BY PRIOR PARENT_ID = ID)
select * from (
select x.*,row_number() over (order by id desc) rn from (
SELECT DISTINCT ID,NAME,TYPE_ID,DESCRIPTION,PARENT_ID FROM CTE1 ORDER BY ID DESC) x) y
pivot
( min(id) ID,min(name) name,min(type_id) type_id,min(description) description,min(parent_id) for rn in (1,2,3)
);