계층형 질의
개요
우리의 현실에는 가지를 쳐가는 계층형 구조의 자료형이 존재한다.
이런 것은 RDBMS에서 어떻게 표현하는가?
효율성을 위해 오른쪽 par_dept_cd와 같이 부모가 누구인지 명시하는 식으로 표현한다.
그러면 이러한 계층과 관련해서 쿼리를 날리고 싶을 때는 어떻게 할까?!
그것이 바로 Hierarchical Query, 계층형 쿼리이다.
구조
select
from
where
start with
connect by [nocycle] [prior] a and b
order siblings by
이것이 계층형 쿼리의 기본적인 방식.
부연을 해보자면,
start with를 통해 루트 데이터를 지정한다.
connect 쪽에는 사이클을 도는 컬럼 = 부모의 값이 적힌 컬럼
을 적어주면 부모에서 자식 방향으로 진행된다.
거꾸로 적으면 당연히 자식에서 부모 방향으로 전개된다.
nocycle을 적어주면 cycle 발생할 경우 데이터를 전개하지 않는다.
order siblings by는 동일 층의 노드들 사이에서의 정렬 기준을 말한다.
여기에서 where는 전체 전개 이후에 필터 처리가 이뤄진다.
또 몇가지 알아야 할 가상 칼럼이 있다.
- level
- 현재 층의 정보.
- 루트는 1이다.
- connect_by_isleaf
- 리프 데이터면 1, 아니면 0
- connect_by_root
- 루트 데이터 값이 담긴다.
- connect_by_iscycle
- 사이클에 해당하는 데이터면 1, 아니면 0
에.. 또 관련 함수도 존재한다!
sys_connect_by_path(출력할 놈들, 구분자)
이런 식으로 하면 전체 경로를 출력해줄 수 있다.
알아야 할 게 많지만 어떤 놈인지만 알아두면 나중에 지피티한테 도움을 빌리면 된다..
SELECT A.INDUTY_CL_CD
, A.INDUTY_CL_NM
, B.INDUTY_CL_SE_CD
, B.INDUTY_CL_SE_NM
, LEVEL LVL
, LPAD(' ', 4*(LEVEL-1))|| A.INDUTY_CL_CD || '(' || A.INDUTY_CL_NM || ')' AS "업종분류코드(명)"
, CONNECT_BY_ISLEAF AS CBI
FROM TB_INDUTY_CL A
, TB_INDUTY_CL_SE B
WHERE A.INDUTY_CL_SE_CD = B.INDUTY_CL_SE_CD
START WITH A.UPPER_INDUTY_CL_CD IS null
CONNECT BY PRIOR A.INDUTY_CL_CD = A.UPPER_INDUTY_CL_CD
ORDER SIBLINGS BY A.INDUTY_CL_CD
;
start는 부모관련 컬럼이 null인 친구부터.
그럼 해당 행들의 id를 connect절에서 B로서 가지고 있는 녀석들을 하위로 잡고, 또 하위로 잡고..
이렇게 결과가 나온다!
LPAD는 빈 칸을 넣는 함수이다.
이런 식으로 경로도 명시해줄 수가 있다
참고로 셀프조인으로도 이것을 구현할 수는 있다.
셀프 조인이란 건 위의 조인들처럼 실체가 있는 무엇이라기 보단 그냥 표현이다.
말그대로 자기 자신을 조인하는 방식을 말한다.
대신 층이 깊어질 때 그걸 일일히 셀프 조인하는 건..
알아서..