CREATE TABLE TEST08 (부문 VARCHAR2(5) NOT NULL,
부서 VARCHAR2(5) NOT NULL,
직급 VARCHAR2(2) NOT NULL,
지역 VARCHAR2(6) NOT NULL,
직원수 NUMBER,
CONSTRAINT TEST08_PK PRIMARY KEY (부문,부서,직급,지역)
);
INSERT INTO TEST08
SELECT SITE,DEPT,LEV,LOCAL,DECODE(MOD(ROWNUM,2),0,2,1)
FROM (SELECT 'SITE1' SITE FROM DUAL UNION ALL SELECT 'SITE2' SITE FROM DUAL) A,
(SELECT 'DEPT1' DEPT FROM DUAL UNION ALL SELECT 'DEPT2' DEPT FROM DUAL UNION ALL
SELECT 'DEPT3' DEPT FROM DUAL UNION ALL SELECT 'DEPT4' DEPT FROM DUAL) B,
(SELECT '서울' LOCAL FROM DUAL UNION ALL SELECT '경기' LOCAL FROM DUAL UNION ALL
SELECT '경상' LOCAL FROM DUAL UNION ALL SELECT '전라' LOCAL FROM DUAL) C,
(SELECT 'A' LEV FROM DUAL UNION ALL SELECT 'B' LEV FROM DUAL UNION ALL
SELECT 'C' LEV FROM DUAL) D;
Parameter 값의 변동에 따른 유연한 Group By
조건.
TABLE : TEST08
------------------------------------
부문 VARCHAR2(5)
부서 VARCHAR2(5)
직급 VARCHAR2(2)
지역 VARCHAR2(6)
직원수 NUMBER
부문 부서 직급 지역 직원수
----- ----- ---- ------ --------
SITE1 DEPT1 A 서울 2
SITE2 DEPT1 A 서울 1
SITE1 DEPT1 B 서울 1
SITE2 DEPT3 B 서울 1
SITE2 DEPT2 C 서울 2
SITE2 DEPT3 C 서울 2
SITE1 DEPT2 A 경기 2
SITE2 DEPT3 C 경상 1
SITE2 DEPT2 A 전라 1
SITE1 DEPT3 B 서울 1
SITE1 DEPT4 B 서울 1
SITE1 DEPT4 C 서울 2
SITE2 DEPT1 A 경기 2
SITE1 DEPT4 C 경상 1
SITE1 DEPT1 A 전라 1
점점점......
문제.
STORED PROCEDURE 또는 일반 APPLICATION PROGRAM 중
다음과 같은 경우가 발생한다.
PARAMETER 값이 하나 또는 그이상 들어오는데 그 순서대로
TEST08의 DATA를 GROUP지어 직원수의 SUM을 보고싶다.
TEST08의 경우 4개의 GROUP BY 인자가 있으므로 PARAMETER1 ~ 3
까지가 들어온다고 가정하면,
PARAM1,PARAM2,PARAM3를 PARAMETER로 받는다.
예를들어, PARAMETER 순서대로 부문,부서,직급이 들어오면
그 순서대로 GROUP 지은 직원수가 나와야하고,
부서,직급이 들어오면 두개만,부서만 들어오면 부서별로만
GROUP을 지어 그직원수의 합을 보여주는 문장을 하나의 SQL로
만들고 싶다.
생각.
말 그대로 GROUP BY 될 순서및 인자가 상황에 따라서 바뀐다.
그때마다 각 경우의 수를 따져서 IF를 만들고 하나의 IF에
하나의 GROUP BY 된 SQL 을 달아주는 것도 비 효율적이다.
한번에 해결하자느게 목표다.
엿보기1.IF 로 조건 분기가 가능한 현상은 SELECT 절에서
대부분 DECODE로 해결이 가능하다.
엿보기2.SELECT절에서 IF가 사용 가능하다면 다음과 같이 될 것이다.
SELECT
IF PARAM1 = 부문 THEN 부문
ELSIF PARAM1 = 부서 THEN 부서
ELSIF PARAM1 = 직급 THEN 직급
ELSE PARAM1 = 지역 THEN 지역 GR1,
IF PARAM2 = 부문 THEN 부문
ELSIF PARAM2 = 부서 THEN 부서
ELSIF PARAM2 = 직급 THEN 직급
ELSE PARAM2 = 지역 THEN 지역 GR2,
IF PARAM3 = 부문 THEN 부문
ELSIF PARAM3 = 부서 THEN 부서
ELSIF PARAM3 = 직급 THEN 직급
ELSE PARAM3 = 지역 THEN 지역 GR3,
SUM(직원수)
FROM TEST08
GROUP BY 1,2,3;
해법.
아주 간단하다.
길게 생각할 필요도 없이 있는 기능을 그냥 이용하면된다.
단지 이렇게도 이용을 할 수가 있다는 것이 요점일 뿐이다.
엿보기에 있는 문장을 DATABASE가 알아먹게 바꿔만 주면 답이다.
단계1.바꿔보자,
SELECT DECODE('부문','부문',부문,
'부서',부서,
'직급',직급,
'지역',지역) GR1,
DECODE('직급','부문',부문,
'부서',부서,
'직급',직급,
'지역',지역) GR2,
DECODE('지역','부문',부문,
'부서',부서,
'직급',직급,
'지역',지역) GR3,
SUM(직원수) 직원수
FROM TEST08
GROUP BY
DECODE('부문','부문',부문,
'부서',부서,
'직급',직급,
'지역',지역),
DECODE('직급','부문',부문,
'부서',부서,
'직급',직급,
'지역',지역),
DECODE('지역','부문',부문,
'부서',부서,
'직급',직급,
'지역',지역)
이게 전부다.
뒷풀이 .
각 경우를 살펴보자
먼저 PARAM1,2,3에 각각 '부문','직급','지역' 이 들어오면
어떻게 되나?.
SELECT 부문 GR1,
직급 GR2,
지역 GR3,
SUM(직원수) 직원수
FROM TEST08
GROUP BY
부문,직급,지역
위와 같이 되어서 다음과 같은 답이 나올 것이다.
GR1 GR GR3 직원수
----- -- ------ ----------
SITE1 A 경기 4
SITE1 A 경상 4
SITE1 A 서울 4
SITE1 A 전라 4
SITE1 B 경기 4
SITE1 B 경상 4
SITE1 B 서울 4
SITE1 B 전라 4
SITE1 C 경기 4
SITE1 C 경상 4
SITE1 C 서울 4
SITE1 C 전라 4
SITE2 A 경기 8
SITE2 A 경상 8
SITE2 A 서울 8
SITE2 A 전라 8
SITE2 B 경기 8
SITE2 B 경상 8
SITE2 B 서울 8
SITE2 B 전라 8
SITE2 C 경기 8
SITE2 C 경상 8
SITE2 C 서울 8
SITE2 C 전라 8
반면, PARAM1,2,3에 각각 '부문','지역',NULL 이 들어오면
어떻게 되나?.
다시말해서 부문별/지역별 합을 보고싶은 경우이다.
SELECT 부문 GR1,
지역 GR2,
NULL GR3,
SUM(직원수) 직원수
FROM TEST08
GROUP BY
부문,지역,NULL
위와 같이 되어서 다음과 같은 답이 나올 것이다.
GR1 GR2 직원수
----- ------ ----------
SITE1 경기 12
SITE2 경기 24
SITE1 경상 12
SITE2 경상 24
SITE1 서울 12
SITE2 서울 24
SITE1 전라 12
SITE2 전라 24
그런대로 멋있는 기능이다.
GROUP BY 에 DECODE를 썼을경우와 그렇지 않은경우의
PLAN 상의 차이는 없다.
PLAN에 영향을 미치는것은 RULE-BASED OPTIMIZER MODE 에서
주로 WHERE 절이기 때문이다.
이런 기능하나로 줄일 수 있는 일의 양이 SYSTEM에따라 다르겠지만
분명히 있다는 것이다.
열심히 알아둬서 손해볼 건 없다는 사실을 다시한번 상기하기를...
부서 VARCHAR2(5) NOT NULL,
직급 VARCHAR2(2) NOT NULL,
지역 VARCHAR2(6) NOT NULL,
직원수 NUMBER,
CONSTRAINT TEST08_PK PRIMARY KEY (부문,부서,직급,지역)
);
INSERT INTO TEST08
SELECT SITE,DEPT,LEV,LOCAL,DECODE(MOD(ROWNUM,2),0,2,1)
FROM (SELECT 'SITE1' SITE FROM DUAL UNION ALL SELECT 'SITE2' SITE FROM DUAL) A,
(SELECT 'DEPT1' DEPT FROM DUAL UNION ALL SELECT 'DEPT2' DEPT FROM DUAL UNION ALL
SELECT 'DEPT3' DEPT FROM DUAL UNION ALL SELECT 'DEPT4' DEPT FROM DUAL) B,
(SELECT '서울' LOCAL FROM DUAL UNION ALL SELECT '경기' LOCAL FROM DUAL UNION ALL
SELECT '경상' LOCAL FROM DUAL UNION ALL SELECT '전라' LOCAL FROM DUAL) C,
(SELECT 'A' LEV FROM DUAL UNION ALL SELECT 'B' LEV FROM DUAL UNION ALL
SELECT 'C' LEV FROM DUAL) D;
Parameter 값의 변동에 따른 유연한 Group By
조건.
TABLE : TEST08
------------------------------------
부문 VARCHAR2(5)
부서 VARCHAR2(5)
직급 VARCHAR2(2)
지역 VARCHAR2(6)
직원수 NUMBER
부문 부서 직급 지역 직원수
----- ----- ---- ------ --------
SITE1 DEPT1 A 서울 2
SITE2 DEPT1 A 서울 1
SITE1 DEPT1 B 서울 1
SITE2 DEPT3 B 서울 1
SITE2 DEPT2 C 서울 2
SITE2 DEPT3 C 서울 2
SITE1 DEPT2 A 경기 2
SITE2 DEPT3 C 경상 1
SITE2 DEPT2 A 전라 1
SITE1 DEPT3 B 서울 1
SITE1 DEPT4 B 서울 1
SITE1 DEPT4 C 서울 2
SITE2 DEPT1 A 경기 2
SITE1 DEPT4 C 경상 1
SITE1 DEPT1 A 전라 1
점점점......
문제.
STORED PROCEDURE 또는 일반 APPLICATION PROGRAM 중
다음과 같은 경우가 발생한다.
PARAMETER 값이 하나 또는 그이상 들어오는데 그 순서대로
TEST08의 DATA를 GROUP지어 직원수의 SUM을 보고싶다.
TEST08의 경우 4개의 GROUP BY 인자가 있으므로 PARAMETER1 ~ 3
까지가 들어온다고 가정하면,
PARAM1,PARAM2,PARAM3를 PARAMETER로 받는다.
예를들어, PARAMETER 순서대로 부문,부서,직급이 들어오면
그 순서대로 GROUP 지은 직원수가 나와야하고,
부서,직급이 들어오면 두개만,부서만 들어오면 부서별로만
GROUP을 지어 그직원수의 합을 보여주는 문장을 하나의 SQL로
만들고 싶다.
생각.
말 그대로 GROUP BY 될 순서및 인자가 상황에 따라서 바뀐다.
그때마다 각 경우의 수를 따져서 IF를 만들고 하나의 IF에
하나의 GROUP BY 된 SQL 을 달아주는 것도 비 효율적이다.
한번에 해결하자느게 목표다.
엿보기1.IF 로 조건 분기가 가능한 현상은 SELECT 절에서
대부분 DECODE로 해결이 가능하다.
엿보기2.SELECT절에서 IF가 사용 가능하다면 다음과 같이 될 것이다.
SELECT
IF PARAM1 = 부문 THEN 부문
ELSIF PARAM1 = 부서 THEN 부서
ELSIF PARAM1 = 직급 THEN 직급
ELSE PARAM1 = 지역 THEN 지역 GR1,
IF PARAM2 = 부문 THEN 부문
ELSIF PARAM2 = 부서 THEN 부서
ELSIF PARAM2 = 직급 THEN 직급
ELSE PARAM2 = 지역 THEN 지역 GR2,
IF PARAM3 = 부문 THEN 부문
ELSIF PARAM3 = 부서 THEN 부서
ELSIF PARAM3 = 직급 THEN 직급
ELSE PARAM3 = 지역 THEN 지역 GR3,
SUM(직원수)
FROM TEST08
GROUP BY 1,2,3;
해법.
아주 간단하다.
길게 생각할 필요도 없이 있는 기능을 그냥 이용하면된다.
단지 이렇게도 이용을 할 수가 있다는 것이 요점일 뿐이다.
엿보기에 있는 문장을 DATABASE가 알아먹게 바꿔만 주면 답이다.
단계1.바꿔보자,
SELECT DECODE('부문','부문',부문,
'부서',부서,
'직급',직급,
'지역',지역) GR1,
DECODE('직급','부문',부문,
'부서',부서,
'직급',직급,
'지역',지역) GR2,
DECODE('지역','부문',부문,
'부서',부서,
'직급',직급,
'지역',지역) GR3,
SUM(직원수) 직원수
FROM TEST08
GROUP BY
DECODE('부문','부문',부문,
'부서',부서,
'직급',직급,
'지역',지역),
DECODE('직급','부문',부문,
'부서',부서,
'직급',직급,
'지역',지역),
DECODE('지역','부문',부문,
'부서',부서,
'직급',직급,
'지역',지역)
이게 전부다.
뒷풀이 .
각 경우를 살펴보자
먼저 PARAM1,2,3에 각각 '부문','직급','지역' 이 들어오면
어떻게 되나?.
SELECT 부문 GR1,
직급 GR2,
지역 GR3,
SUM(직원수) 직원수
FROM TEST08
GROUP BY
부문,직급,지역
위와 같이 되어서 다음과 같은 답이 나올 것이다.
GR1 GR GR3 직원수
----- -- ------ ----------
SITE1 A 경기 4
SITE1 A 경상 4
SITE1 A 서울 4
SITE1 A 전라 4
SITE1 B 경기 4
SITE1 B 경상 4
SITE1 B 서울 4
SITE1 B 전라 4
SITE1 C 경기 4
SITE1 C 경상 4
SITE1 C 서울 4
SITE1 C 전라 4
SITE2 A 경기 8
SITE2 A 경상 8
SITE2 A 서울 8
SITE2 A 전라 8
SITE2 B 경기 8
SITE2 B 경상 8
SITE2 B 서울 8
SITE2 B 전라 8
SITE2 C 경기 8
SITE2 C 경상 8
SITE2 C 서울 8
SITE2 C 전라 8
반면, PARAM1,2,3에 각각 '부문','지역',NULL 이 들어오면
어떻게 되나?.
다시말해서 부문별/지역별 합을 보고싶은 경우이다.
SELECT 부문 GR1,
지역 GR2,
NULL GR3,
SUM(직원수) 직원수
FROM TEST08
GROUP BY
부문,지역,NULL
위와 같이 되어서 다음과 같은 답이 나올 것이다.
GR1 GR2 직원수
----- ------ ----------
SITE1 경기 12
SITE2 경기 24
SITE1 경상 12
SITE2 경상 24
SITE1 서울 12
SITE2 서울 24
SITE1 전라 12
SITE2 전라 24
그런대로 멋있는 기능이다.
GROUP BY 에 DECODE를 썼을경우와 그렇지 않은경우의
PLAN 상의 차이는 없다.
PLAN에 영향을 미치는것은 RULE-BASED OPTIMIZER MODE 에서
주로 WHERE 절이기 때문이다.
이런 기능하나로 줄일 수 있는 일의 양이 SYSTEM에따라 다르겠지만
분명히 있다는 것이다.
열심히 알아둬서 손해볼 건 없다는 사실을 다시한번 상기하기를...
댓글 0
번호 | 제목 | 글쓴이 | 날짜 | 조회 수 |
---|---|---|---|---|
86 | 중복 data를 찾아 한번만 display하는 방법 | 운영자 | 2002.11.23 | 3428 |
85 | 중복 data를 찾아 모두 display 하는 방법 | 운영자 | 2002.11.23 | 3070 |
84 | oracle의 procedure에서의 여러 리턴값의 활용 예 | 운영자 | 2002.10.18 | 8301 |
83 | 특정문자까지의 왼쪽 문자열 반환 function | 운영자 | 2002.10.18 | 4044 |
82 | 중복자료 확인 및 삭제 | 운영자 | 2002.09.25 | 3259 |
81 | RECORD단위 DATA를 COLUMN단위로 | 운영자 | 2002.09.18 | 3681 |
80 | 누계 COLUMN이 없는 TABLE에 누계 값을 보자 (부등호 JOIN) | 운영자 | 2002.09.18 | 5104 |
79 | 바로이전 ROW의 값을 참조하고자 할때 | 운영자 | 2002.09.18 | 8619 |
78 | 누계 COLUMN이 없는 TABLE에 누계 값을 보자 (IN-LINE VIEW) | 운영자 | 2002.09.18 | 3123 |
77 | 자기보다 작은값중 최대값 하나만 읽어오기 | 운영자 | 2002.09.18 | 4588 |
76 | DATA COPY를 이용한 QUERY | 운영자 | 2002.09.18 | 3186 |
» | PARAMETER값 변경에따른 유연한 GROUP BY | 운영자 | 2002.09.18 | 4127 |
74 | PAIRWISE 와 NONPAIRWISE | 운영자 | 2002.09.18 | 2697 |
73 | 동일한 값 안보여주기 | 운영자 | 2002.09.18 | 2969 |
72 | 소계/합계 함께 보기 | 운영자 | 2002.09.18 | 3134 |
71 | 석차구하기 | 운영자 | 2002.09.18 | 2960 |
70 | COLUMN을 ROW로 | 운영자 | 2002.09.18 | 6135 |
69 | 최대값과 최소값을 뺀 평균 | 운영자 | 2002.09.18 | 4177 |
68 | 누계를 구하는 또한가지 방법 | 운영자 | 2002.09.18 | 3209 |
67 | 그룹 단위별 일련번호 붙이기 | 운영자 | 2002.09.18 | 5754 |