SQL:对单个结果进行反向树遍历

问题描述

我的桌子看起来像这样:

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和层次结构查询来解决此问题。

Demo

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)
  );

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...