사용자 도구

사이트 도구


postgresql:recursive

Reccursive Query

WITH RECURSIVE MENU_LIST(ID, PARENT_ID, MENU_CD, MENU_NAME, ORD, DEPTH, PATH, CYCLE) AS (
SELECT ID, PARENT_ID, MENU_CD, MENU_NAME, ORD,
               1 DEPTH,
               -- ARRAY[ID::text],
               ARRAY[ID],
              FALSE
  FROM GOV_APPMENU A
WHERE MENU_CD = 'ADM'
 
UNION ALL
/* 하위 데이터를 찾아가기 위한 반복조건 쿼리 */
SELECT A.ID, A.PARENT_ID, A.MENU_CD, A.MENU_NAME, A.ORD,
               B.DEPTH + 1 DEPTH,
               --ARRAY_APPEND(B.PATH, A.ID::text),
               B.PATH || A.ID,
               A.ID = any(B.PATH)
  FROM GOV_APPMENU A, MENU_LIST B
 WHERE A.PARENT_ID = B.ID
   AND NOT CYCLE
)
/* View 쿼리 */
SELECT ID, PARENT_ID, MENU_CD, MENU_NAME, ORD, DEPTH, PATH, CYCLE
FROM MENU_LIST
-- WHERE DEPTH IN (2,4)
ORDER BY DEPTH, ORD

CYCLE은 RECURSIVE를 통한 재귀 쿼리 수행 시 성능상의 문제 해결하기 위함.

UNION ALL 다음의 반복조건 쿼리가 수행되면 CYCLE이 false이기 때문에 SELECT문이 수행 되고 검색된 자식 node의 ID 값이 배열(ARRAY[A.CONTS_ID::text])에 추가(ARRAY_APPEND(B.PATH, A.CONTS_ID::text)) 됨.

ANY(B.PATH)는 PATH 배열에 자신의 ID값이 있는 지를 검사하여

 이미 찾은 값에 대해서는 더 이상 데이터 검색을 수행하지 않도록 함.

배열에는 DataType이 int, text인 형태만 담을 수 있으므로

배열에 담을 varchar타입의 컬럼 뒤에 ::text 를 붙여 형태를 변환 해줌.오라클로 구현할때도 쉽지 않은 계층형 쿼리… 역시 PostgreSQL로 작성하려 해도 쉽지는 않다.

오라클과 달리 WITH RECURSIVE를 이용해서 트리 구조의 계층형 쿼리 구현하는 방법에 대해 정리해 보았다. 다음에 시간되면 데이터를 행에서 열로 전환하는 PIVOT 기능 구현에 대해 정리해 보고자 한다.

postgresql/recursive.txt · 마지막으로 수정됨: 2025/04/15 10:05 저자 127.0.0.1