사용자 도구

사이트 도구


postgresql:recursive

차이

문서의 선택한 두 판 사이의 차이를 보여줍니다.

차이 보기로 링크

양쪽 이전 판이전 판
다음 판
이전 판
postgresql:recursive [2023/04/18 14:03] taekgupostgresql:recursive [2025/04/15 10:05] (현재) – 바깥 편집 127.0.0.1
줄 1: 줄 1:
 +====== Reccursive Query ======
  
 +<code sql>
 +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
 +</code>
 +
 +=== 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 기능 구현에 대해 정리해 보고자 한다.