일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 파이썬
- 백준 1756
- react
- 정규화
- SAA-C02
- 프로그래머스 조건에 맞는 개발자 찾기
- 알고리즘
- github
- 백준 크리문자열
- 깃허브
- 데이터베이스
- 리스트 컴프리헨션
- 백준 24499 파이썬
- sql
- 백준 11059
- join
- ROWNUM
- AWS
- SQLD
- 백준 2852
- Today
- Total
-
[SQLD] #023 SQL 활용 - 계층형 질의와 셀프 조인 본문
목차
1. 계층형 질의
2. 셀프 조인
1. 계층형 질의
테이블에 계층형 데이터가 존재하는 경우 데이터를 조회하기 위해서 계층형 질의(Hierarchical Query)를 사용한다.
계층형 데이터란 동일 테이블에 계층적으로 상위와 하위 데이터가 포함된 데이터를 말한다. 엔터티를 순환관계 데이터 모델로 설계할 경우에 계층형 데이터가 발생하는데, 순환관계 데이터 모델의 예로는 조직, 사원, 메뉴 등이 있다.
1. Oracle 계층형 질의
- START WITH 절은 계층 구조 전개의 시작 위치를 지정하는 구문이다. 즉, 루트 데이터를 지정한다.
- CONNECT BY 절은 다음에 전개될 자식 데이터를 지정하는 구문이다. 자식 데이터는 CONNECT BY 절에 주어진 조건을 만족해야한다.
- PRIOR : CONNECT BY 절에 사용되며, 현재 읽은 칼럼을 지정한다.
[PRIOR 자식 = 부모] 형태를 사용하면 계층 구조에서 부모 → 자식 방향으로 전개하는 순방향 전개를 한다.
[PRIOR 부모 = 자식] 형태를 사용하면 반대로 자식 → 부모 방향으로 전개하는 역방향 전개를 한다.
- NOCYCLE : 데이터를 전개하면서 이미 나타났던 동일한 데이터가 전개 중에 다시 나타난다면 이것을 '사이클이 형성되었다' 라고 말한다. 사이클이 발생한 데이터는 런타임 에러가 나지만 NOCYCLE을 추가하면 사이클이 발생한 이후의 데이터는 전개하지 않는다.
- ORDER SIBLINGS BY : 형제 노드 사이에서 정렬을 수행한다.
- WHERE : 모든 전개를 수행한 후에 지정된 조건을 만족하는 데이터만 추출한다. (필터링)
Oracle은 계층형 질의를 사용할 때 다음과 같은 가상 칼럼을 제공한다.
순방향 전개 예제
다음은 아래 그림에서 3번의 샘플 데이터를 계층형 질의 구문을 이용해서 조회한 것이다. 여기서는 결과 데이터를 들여쓰기 하기 위해 LPAD 함수를 사용했다.
SELECT LEVEL,
LPAD(' ', 4 * (LEVEL-1)) || 사원 사원,
관리자,
CONNECT_BY_ISLEAF ISLEAF
FROM 사원
START WITH 관리자 IS NULL
CONNECT BY PRIOR 사원 = 관리자;
- A는 루트 데이터이기 때문에 레벨이 1이다. A의 하위 데이터인 B, C는 레벨이 2이다. C의 하위 데이터인 D, E는 레벨이 3이다.
- 리프데이터는 B, D, E이다.
- 관리자 → 사원 방향으로의 전개이기 때문에 순방향 전개이다.
역방향 전개 예제
다음은 사원 'D' 로부터 자신의 상위 관리자를 찾는 역방향 전개의 예다.
SELECT LEVEL,
LPAD(' ', 4 * (LEVEL-1)) || 사원 사원,
관리자,
CONNECT_BY_ISLEAF ISLEAF
FROM 사원
START WITH 사원 = 'D'
CONNECT BY PRIOR 관리자 = 사원;
계층형 질의 함수
Oracle은 계층형 질의를 사용할 때 사용자의 편의성을 제공하기 위해 아래와 같은 함수를 제공한다.
위의 두 함수를 사용한 예제는 다음과 같다.
SELECT CONNECT_BY_ROOT 사원 루트사원, SYS_CONNECT_BT_PATH(사원, '/') 경로, 사원, 관리자
FROM 사원
START WITH 관리자 IS NULL
CONNECT BY PRIOR 사원=관리자
2. SQL Server 계층형 질의
SQL Server 2005 버전부터 하나의 질의로 원하는 결과를 얻을 수 있게 바뀌었다.
WITH EMPLOYEES_ANCHOR AS
(SELECT EMPLOYEEID,
LASTNAME,
FIRSTNAME,
REPORTSTO,
0 AS LEVEL
FROM EMPLOYEES
WHERE REPORTSTO IS NULL
UNION ALL /* 재귀 호출의 시작점 */
SELECT R.EMPLOYEEID,
R.LASTNAME,
R.FIRSTNAME,
R.REPORTSTO,
A.LEVEL + 1
FROM EMPLOYEES_ANCHOR A, EMPLOYEES R
WHERE A.EMPLOYEEID = R.REPORTSTO )
SELECT LEVEL,
EMPLOYEEID,
LASTNAME,
FIRSTNAME,
REPORTSTO
FROM EMPLOYEES_ANCHOR GO
WITH 절의 CTE 쿼리를 보면, UNION ALL 연산자로 쿼리 두개를 결합했다. 둘 중 위에 있는 쿼리를 '앵커 멤버' 라고 하고, 아래에 있는 쿼리를 '재귀 멤버' 라고 한다. 아래는 재귀적 쿼리의 처리 과정이다.
1. CTE 식을 앵커 멤버와 재귀 멤버로 분할한다.
2. 앵커 멤버를 실행하여 첫번째 호출 또는 기본 결과 집합을 만든다.
3. Ti는 입력으로 사용하고 Ti+1은 출력으로 사용하여 재귀 멤버를 실행한다.
4. 빈 집합이 반환될 때까지 3단계를 반복한다.
5. 결과 집합을 반환한다. 이것은 T0에서 Tn까지의 UNION ALL 이다.
2. 셀프 조인
셀프 조인이란 동일 테이블 사이의 조인을 말한다.
따라서 FROM 절에 동일 테이블이 두번 이상 나타난다. 동일 테이블 사이에 조인을 수행하면 테이블과 칼럼 이름이 모두 동일하기 때문에 식별을 위해 반드시 테이블 별칭(Alias)을 사용해야 한다. 그리고 칼럼에도 모두 테이블 별칭을 사용해서 어느 테이블의 칼럼인지 식별해주어야 한다.
셀프 조인에 대한 기본적인 사용법은 다음과 같다.
SELECT ALIAS명1.칼럼명, ALIAS명2.칼럼명, ...
FROM 테이블1 ALIAS명1, 테이블2 ALIAS명2
WHERE ALIAS명1.칼럼명2 = ALIAS명2.칼럼명1;
SELECT E1.사원,
E1.관리자,
E2.관리자 차상위_관리자
FROM 사원 E1,
사원 E2
WHERE E1.관리자 = E2.사원
ORDER BY E1.사원;
-- 실행 결과
B A C A D C A E C A
- 셀프 조인은 동일한 테이블이지만 위 그림과 같이 두개의 서로 다른 테이블을 사용하는 것과 동일하다.
- 자신과 자신의 직속 관리자는 동일한 행에서 데이터를 구할 수 있으나 차상위 관리자는 바로 구할 수 없다. 차상위 관리자를 구하기 위해서는 자신의 직속 관리자를 기준으로 사원 테이블과 한번 더 셀프조인을 수행해야 한다.
- 결과에서 A에 대한 정보는 누락되었다. 내부 조인(INNER JOIN)을 사용할 경우 자신의 관리자가 존재하지 않는 경우에는 관리자 테이블에서 조인할 대상이 존재하지 않기 때문에 해당 데이터는 누락된다. 따라서 이를 방지하기 위해서는 아우터 조인을 사용해야한다.
다음은 아우터 조인을 사용한 예이다.
SELECT E1.사원,
E1.관리자,
E2.관리자 차상위_관리자
FROM 사원 E1
LEFT OUTER JOIN 사원 E2
ON (E1.관리자 = E2.사원)
ORDER BY E1.사원;
-- 실행 결과
A B A C A D C A E C A
출처
이 글의 내용은 모두 한국데이터베이스진흥원이 출판한 SQL 전문가 가이드 2013 Edition을 기본으로 한다.
'SQLD' 카테고리의 다른 글
[SQLD] #025 SQL 활용 - 그룹 함수 (0) | 2021.05.13 |
---|---|
[SQLD] #024 SQL 활용 - 서브 쿼리 (0) | 2021.05.10 |
[SQLD] #022 SQL 활용 - 집합 연산자 (0) | 2021.05.09 |
[SQLD] #021 SQL 활용 - 표준 조인 (0) | 2021.05.06 |
[SQLD] #020 SQL 기본 - JOIN (0) | 2021.05.06 |