2017-03-21 1 views
1

상위/하위 관계가 포함 된 데이터베이스가 있고 하위 ID가 같은 행에 모든 상위 ID를 갖도록 데이터를 축소하려고합니다.재귀 조인 PostgreSQL 하위 ID의 모든 상위 ID 찾기

Name | ID | Top_Level | Sub_Level | Sub_Level_2 
A   1  NULL 
B   2   1 
C   3   1  2 
D   4   1  2   3 

가 좀 재귀와 함께 놀았지만 정확한 결과를 얻을 수 없습니다 계속 진행하는 방법을 잘 모르겠습니다 않았다

Name | ID | Parent_ID 
A   1  NULL 
B   2  1 
C   3  2 
D   4  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

하지 매우 우아하지만 지금은 다른 아무것도 생각할 수 없다 :

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 모두 단일 행만 있기 때문에 교차 조인은 결과를 변경하지 않지만 이러한 값을 더 쉽게 사용하게합니다.

아마도 가장 효율적인 방법은 아닙니다.

온라인 예 : http://rextester.com/KVOG87512

관련 문제