1

여러 수준의 상위, 하위 레코드에서 최상위 루트 수준 상위 레코드를 얻기 위해 Oracle SQL 문을 작성하려고합니다. 테이블 구조는 아래와 같습니다. 아래의 최상위 루트 부모는 parent_membership_id 53887이며,이 부모 레코드에는 다른 자식에 대한 부모 인 여러 자식이 있습니다. 내가 원하는 것은 쿼리가 200326의 멤버를 말하고, 쿼리가 루트 멤버 53887을 다시 불러 오거나 쿼리 200322에 루트 멤버 53887을 얻는 쿼리입니다. 내가 뭘 하려는지 알 것 같아요. 고마워요.다수의 부모/자식 레코드에서 Oracle SQL 최상위 부모 레코드 얻기

CREATE TABLE MEMBERSHIP_LINK 
(MEMBERSHIP_LINK_ID  NUMBER(10)   NOT NULL, 
    CHILD_MEMBERSHIP_ID  NUMBER(10)   NOT NULL, 
    PARENT_MEMBERSHIP_ID  NUMBER(10)   NOT NULL); 

Insert into MEMBERSHIP_LINK 
    (MEMBERSHIP_LINK_ID, CHILD_MEMBERSHIP_ID, PARENT_MEMBERSHIP_ID) 
Values 
    (35, 53890, 53887); 
Insert into MEMBERSHIP_LINK 
    (MEMBERSHIP_LINK_ID, CHILD_MEMBERSHIP_ID, PARENT_MEMBERSHIP_ID) 
Values 
    (24475, 200322, 53887); 
Insert into MEMBERSHIP_LINK 
    (MEMBERSHIP_LINK_ID, CHILD_MEMBERSHIP_ID, PARENT_MEMBERSHIP_ID) 
Values 
    (24476, 200322, 53887); 
Insert into MEMBERSHIP_LINK 
    (MEMBERSHIP_LINK_ID, CHILD_MEMBERSHIP_ID, PARENT_MEMBERSHIP_ID) 
Values 
    (34, 53889, 53888); 
Insert into MEMBERSHIP_LINK 
    (MEMBERSHIP_LINK_ID, CHILD_MEMBERSHIP_ID, PARENT_MEMBERSHIP_ID) 
Values 
    (5941, 112177, 53889); 
Insert into MEMBERSHIP_LINK 
    (MEMBERSHIP_LINK_ID, CHILD_MEMBERSHIP_ID, PARENT_MEMBERSHIP_ID) 
Values 
    (33, 53888, 53890); 
Insert into MEMBERSHIP_LINK 
    (MEMBERSHIP_LINK_ID, CHILD_MEMBERSHIP_ID, PARENT_MEMBERSHIP_ID) 
Values 
    (24477, 200323, 200322); 
Insert into MEMBERSHIP_LINK 
    (MEMBERSHIP_LINK_ID, CHILD_MEMBERSHIP_ID, PARENT_MEMBERSHIP_ID) 
Values 
    (24478, 200323, 200322); 
Insert into MEMBERSHIP_LINK 
    (MEMBERSHIP_LINK_ID, CHILD_MEMBERSHIP_ID, PARENT_MEMBERSHIP_ID) 
Values 
    (24479, 200325, 200323); 
Insert into MEMBERSHIP_LINK 
    (MEMBERSHIP_LINK_ID, CHILD_MEMBERSHIP_ID, PARENT_MEMBERSHIP_ID) 
Values 
    (24480, 200326, 200323); 
COMMIT; 
+1

'MEMBERSHIP_LINK_ID'의 24477과 24478은 같은 관계를 나타내는 것이 의도입니까? – Sentinel

+0

부모 나 자식과 아무런 관련이없는 유일한 키 –

+1

'MEMBERSHIP_LINK_ID'의 24477과 24478은 모두 'CHILD_MEMBERSHIP_ID'와 (과) 'PARENT_MEMBERSHIP_ID'(200323과 200322)가 동일하므로 'MEMBERSHIP_LINK_ID'의 24477과 24478이 같은 관계를 나타냅니다. – Sentinel

답변

0

이 코드는 작동하지만 동일한 관계를 정의하는 레코드 24477 및 24478로 인해 고유 한 연산자가 필요합니다. PARENT_MEMBERSHIP_IDCONNECT BY 절에 PRIOR 키워드를 배치

SELECT DISTINCT ML.PARENT_MEMBERSHIP_ID 
    FROM MEMBERSHIP_LINK ml 
    WHERE CONNECT_BY_ISLEAF = 1 -- Limit to the "Root" element(s) 
    START WITH ML.CHILD_MEMBERSHIP_ID = :decendent_id 
CONNECT BY ML.CHILD_MEMBERSHIP_ID = prior ML.PARENT_MEMBERSHIP_ID; 

루트으로 이송 될 수있는 트리를 야기하고, "루트"노드 잎을합니다. 당신이 공유 조상을 찾기 위해 노력하는 경우

는 다음 다른 접근 방식이 필요하다 :이에서

WITH ancestry AS 
    (SELECT DISTINCT CONNECT_BY_ROOT CHILD_MEMBERSHIP_ID child_id 
     , ML.PARENT_MEMBERSHIP_ID ancestor_id 
     , level generation_gap 
     , CONNECT_BY_ISLEAF 
     FROM MEMBERSHIP_LINK ml 
    START WITH ML.CHILD_MEMBERSHIP_ID in (:Descendent_ID1,:Descendent_ID2) 
    CONNECT BY ML.CHILD_MEMBERSHIP_ID = prior ML.PARENT_MEMBERSHIP_ID 
) 
SELECT ancestor_id 
    FROM ancestry 
    WHERE child_id = :Descendent_ID1 
INTERSECT 
SELECT ancestor_id 
    FROM ancestry 
    WHERE child_id = :Descendent_ID2; 

당신이 가장 최근 (막내) 공유 조상, 가장 오래된 공유 조상과 공통 계보를 확인할 수 있습니다 :

WITH ancestry AS (
    SELECT DISTINCT CONNECT_BY_ROOT CHILD_MEMBERSHIP_ID child_id 
     , ML.PARENT_MEMBERSHIP_ID ancestor_id 
     , level generation_gap 
     , CONNECT_BY_ISLEAF 
    FROM MEMBERSHIP_LINK ml 
    START WITH ML.CHILD_MEMBERSHIP_ID in (:Descendent_ID1,:Descendent_ID2) 
    CONNECT BY ML.CHILD_MEMBERSHIP_ID = prior ML.PARENT_MEMBERSHIP_ID 
), common AS (
    SELECT ancestor_id 
    FROM ancestry 
    WHERE child_id = :Descendent_ID1 
INTERSECT 
    SELECT ancestor_id 
    FROM ancestry 
    WHERE child_id = :Descendent_ID2 
) 
SELECT MIN(a.ANCESTOR_ID) keep(dense_rank FIRST ORDER BY a.GENERATION_GAP) Youngest_Ancestor 
     , LISTAGG(a.ANCESTOR_ID, '->') within group (order by a.GENERATION_GAP) common_lineage 
     , MIN(a.ANCESTOR_ID) keep(dense_rank FIRST ORDER BY a.GENERATION_GAP desc) Oldest_Ancestor 
    FROM ancestry a 
    JOIN common c 
    ON a.ancestor_id = c.ancestor_id 
    WHERE a.child_id = :Descendent_ID1; 
0

답변을 해결했습니다. SQL은 아래와 같습니다.

SELECT DISTINCT meli.parent_membership_id 
     FROM MEMBERSHIP_LINK meli 
     WHERE LEVEL = (SELECT max(level) 
      FROM MEMBERSHIP_LINK meli_in 
      START WITH meli_in.child_membership_id = :membership_id 
      CONNECT BY meli_in.child_membership_id = PRIOR meli_in.parent_membership_id) 
     START WITH meli.child_membership_id = :membership_id 
     CONNECT BY meli.child_membership_id = prior meli.parent_membership_id 
관련 문제