DataBase > Oracle/Tibero

[db] 계층구조 쿼리, merge update

#oracle#tibero

hierarchy 구조 분석

START WITH 트리의 시작점 (자신도 포함)
CONNECT BY 부모 자식간의 관계
CONNECT BY PRIOR 자식=부모 부모 > 자식(PRIOR)순으로 취득
CONNECT BY PRIOR 부모=자식 자식 > 부모(PRIOR)순으로 취득
ORDER SIBLINGS BY 같은레벨간 정렬

Sample쿼리

SELECT 
      A.*
    , REPLACE(SYS_CONNECT_BY_PATH(A.DEPT_NM, '>'),'>전체>','') AS FULL_NAME 
    , LEVEL
FROM TB_DEPT A
WHERE 
            A.USE_YN = 'Y'
    AND A.DEPT_CD <> '001'  ※ where절은 해당 조건만 검색하지 않는다.
START WITH A.DEPT_CD='001'
CONNECT BY NOCYCLE PRIOR 
            A.DEPT_CD = A.PARENT_CD 
    AND A.DEPT_CD <> '12345'  ※ 지정조건 이하 검색을 하지 않는다. (조건만나면 더이상 타고가며 검색안함)
ORDER SIBLINGS BY A.VIEW_ORD

 

계층형 쿼리

SELECT
     LEVEL
    ,CONNECT_BY_ISLEAF AS ISLEAF
    ,CODE
    ,UPCODE
    ,PRIOR CODE AS SAME_CODE
      * upcode 와 동일한 값을 취득한다.
    ,LPAD(' ', 4*(LEVEL-1)) || NAME
FROM 
    TBL_CODE    
WHERE
    USE_YN = 'Y'
START WITH UPCODE = 'ROOT'
CONNECT BY PRIOR CODE = UPCODE AND LEVEL < 4
    * LEVEL < 4 를 WHERE절에 넣으면 전체 취득 후 필터링하지만 CONNECT BY에 넣으면 필터링후 취득해 효과적이다.
ORDER SIBLINGS BY DSP_ORDER    

LEVEL

가상열로 계층형쿼리의 레벨을 표시
비계층형에서는 계층이 없으므로 항상 0이다
START WITH ~ CONNECT BY 를 사용시 계층의 레벨을 표시가능

1 ~ n 까지 숫자생성하기

    SELECT LEVEL FROM DUAL CONNECT BY LEVEL < 10;

1월 ~ 12월까지 출력

    SELECT LPAD(LEVEL,2,0)||'월' AS MONTH FROM DUAL CONNECT BY LEVEL < 13;

특정일 부터 날짜 출력 (21/12/01일 부터 34일 후까지 날짜 출력)

    SELECT TO_DATE('20211201', 'YYYYMMDD') + (LEVEL-1) AS DT FROM DUAL CONNECT BY LEVEL < 35;
 

LPAD (좌측 공간채우기)

LPAD("값", "총 문자길이", "채움문자") : RPAD(뒤에)
LPAD(' ', 4) = LPAD(' ', 4, ' ') : 앞에 4공백채우기
LPAD('_', 4, '_') : 앞에 4개 _로 채우기

CONNECT_BY_ISLEAF (자식존재 여부체크)

자신이 맨끝(자식이 없음) : 1
자식노드가 있으면 : 0

SELECT PRIOR (부모 확인)

PRIOR이 SELECT문에 있으면, 현재행의 부모를 가르킴

START WITH

계층구조가 어떤 행에서 시작할지를 지정
조건이 계층 상하에 존재할 경우 각각 조건별 계층이 생성된다.

CONNECT BY PRIOR

PRIOR(이전의) 행을 찾아가며 전부 검색한다.
계층 하위구조표시의 경우 (PRIOR 하위 = 상위) 형식으로 상위부터 바로전의 하위를 찾아가는 형식

계층구조 FULL NAME 취득 후 업데이트 하기

※ 부서정보의 전체패스를 업데이트 하기

MERGE INTO DEPT A
USING (
        SELECT DEPT_CD, 
            REPLACE(SYS_CONNECT_BY_PATH(DEPT_NM, '>'),'>전체>','') AS FULLNAME
        FROM DEPT
        START WITH DEPT_CD=0
        CONNECT BY NOCYCLE PRIOR DEPT_CD = PARENT_CD
        ) B 
ON (A.DEPT_CD = B.DEPT_CD)
WHEN MATCHED THEN
UPDATE SET A.FULL_PATH = B.FULLNAME;

입력 부서의 풀패스(전체경로)를 취득하는 쿼리

SELECT 
    LISTAGG(DEPT_NM, ' ') WITHIN GROUP (ORDER BY RN DESC)
FROM 
(
    SELECT 
        A.DEPT_NM, ROWNUM RN 
    FROM 
        TBL_DEPT A 
    START WITH DEPT_CD = '12300'
    CONNECT BY NOCYCLE PRIOR  UP_CD = DEPT_CD
)