by 마농 계층구조쿼리 CONNECT BY LEVEL SYS_CONNECT_BY_PATH PRIOR NOCYCLE 테스트데이터생성 경우의수 [2014.01.17]
아래는 현재행을 시작점으로 하위에서 상위로 누적합계를 구하는 예제이다.
SELECT empno
, LEVEL lv
, LPAD(' ', (LEVEL-1)*2, ' ') || ename AS ename
, sal
, (SELECT SUM(sal)
FROM emp
START WITH empno = a.empno
CONNECT BY PRIOR empno = mgr
) sum_sal
FROM emp a
START WITH mgr IS NULL
CONNECT BY PRIOR empno = mgr
;
EMPNO LV ENAME SAL SUM_SAL
------- ---------- -------------------- ---------- ----------
7839 1 KING 5000 29025
7566 2 JONES 2975 10875
7788 3 SCOTT 3000 4100
7876 4 ADAMS 1100 1100
7902 3 FORD 3000 3800
7369 4 SMITH 800 800
7698 2 BLAKE 2850 9400
7499 3 ALLEN 1600 1600
7521 3 WARD 1250 1250
7654 3 MARTIN 1250 1250
7844 3 TURNER 1500 1500
7900 3 JAMES 950 950
7782 2 CLARK 2450 3750
7934 3 MILLER 1300 1300
프로젝트 진행시 테스트 데이터 생성이 필요한 경우가 있는데 CONNECT BY LEVEL을 활용하면 손쉽게 테스트 샘플 데이터를 생성 할 수 있다.
아래 예제와 같이 CONNECT BY LEVEL을 사용하면, 특정 LEVEL이 될 때 까지 ROW를 출력하는 것을 알 수 있다.
-- 10개의 ROW를 출력하는 예제이다.
SELECT LEVEL FROM DUAL CONNECT BY LEVEL <= 10;
-- 10개의 ROW가 출력된다.
LEVEL
-------
1
2
3
4
...
10
위 CONNECT BY LEVEL의 원리를 이용하여 아래와 같이 테스트 샘플데이터를 만들어 보자
-- 10 만건의 데이터를 가지는 emp_sample 테이블을 생성하는 예제이다.
CREATE TABLE emp_sample AS
SELECT -- 1. EMPNO(Unique 컬럼)
LEVEL empno,
-- 2. JOB(천만건 데이터를 10개 그룹으로 분류)
'SALESMAN_'||CHR(65 + MOD(LEVEL , 10)) job,
-- 3. HIREDATE(금일+9일까지)
SYSDATE + MOD(LEVEL , 10) hiredate,
-- 4. DEPTNO (0, 10, 20, 30, 40)
MOD(LEVEL ,5)*10 deptno
FROM DUAL
CONNECT BY LEVEL <= 100000;
-- 테이블과 데이터가 정상적으로 생성되었는지 확인해 보자
SELECT * FROM emp_sample WHERE ROWNUM < 10;
EMPNO JOB HIREDATE DEPTNO
----- ----------- -------- ----------
1 SALESMAN_B 11/06/28 10
2 SALESMAN_C 11/06/29 20
3 SALESMAN_D 11/06/30 30
4 SALESMAN_E 11/07/01 40
...
이번 예제는 그림과 같이 (A, B, C) 3개 코드 조합으로 나올 수 있는 모든 경우의 수를 조회하는 예제이다.
아래는 계층구조쿼리를 사용하지 않고, UNION ALL을 이용하여 작성하였다. 아래 쿼리는 self 조인과 UNION ALL 조합의 한계가 있다. 코드의 개수가 늘어날 경우 SQL 수정이 불가피 하다.
WITH test AS
(
SELECT 'A' code FROM dual
UNION ALL SELECT 'B' FROM dual
UNION ALL SELECT 'C' FROM dual
)
SELECT a.code
FROM test a
UNION ALL
SELECT a.code ||'-'|| b.code AS code
FROM test a
, test b
WHERE a.code < b.code
UNION ALL
SELECT a.code ||'-'|| b.code ||'-'|| c.code AS code
FROM test a
, test b
, test c
WHERE a.code < b.code
AND b.code < c.code
;
CODE
---------------
A
B
C
A-B
A-C
B-C
A-B-C
7 rows selected.
아래는 계층구조쿼리를 사용하여 경우의 수를 조회한 예제이다.
WITH test AS ( SELECT 'A' code FROM dual UNION ALL SELECT 'B' FROM dual UNION ALL SELECT 'C' FROM dual ) SELECT SUBSTR(SYS_CONNECT_BY_PATH(code, '-'), 2) code FROM test CONNECT BY PRIOR code < code ORDER BY LEVEL, code ; CODE ----------------- A B C A-B A-C B-C A-B-C 7 rows selected.
이번 예제는 순서까지 고려한 모든 경우의 수이다.
WITH test AS ( SELECT 'A' code FROM dual UNION ALL SELECT 'B' FROM dual UNION ALL SELECT 'C' FROM dual ) SELECT SUBSTR(SYS_CONNECT_BY_PATH(code, '-'), 2) code FROM test CONNECT BY NOCYCLE PRIOR code != code ORDER BY LEVEL, code ; CODE ------------------- A B C A-B A-C B-A B-C C-A C-B A-B-C A-C-B B-A-C B-C-A C-A-B C-B-A 15 rows selected.
- 강좌 URL : http://www.gurubee.net/lecture/2681
- 구루비 강좌는 개인의 학습용으로만 사용 할 수 있으며, 다른 웹 페이지에 게재할 경우에는 출처를 꼭 밝혀 주시면 고맙겠습니다.~^^
- 구루비 강좌는 서비스 제공을 위한 목적이나, 학원 홍보, 수익을 얻기 위한 용도로 사용 할 수 없습니다.