티스토리 뷰
최근 맞닥뜨린 문제는 아래와 같다.
MAIN_TABLE
KEY TYPE
1 AB
2 AB
SUB_TABLE_A (TYPE A의 정보를 갖고 있는 테이블)
KEY TYPE VALUE
1 A 10
2 A 20
SUB_TABLE_B (TYPE B의 정보를 갖고 있는 테이블)
KEY TYPE VALUE
1 B 30
2 B 40
--> 이 데이터를 아래처럼 보여주고 싶을 경우
KEY TYPE A_VALUE B_VALUE
1 AB 10 30
2 AB 20 40
먼저 A_VALUE와 B_VALUE 의 값은 정수형이다. (어쩌면 정수형이기 때문에 #1 의 방법으로 쉽게 해결이 돼서 참 다행이라 생각했었지만 #2 를 알고 난 후에는 정수든 뭐든... 이라는 생각이..)
보통 1개 이상의 레코드를 합칠때는 오라클 버전별로 아래의 함수들을 사용할 것이다.
9i : XMLAGG
10g: WM_CONCAT
11g: LISTAGG
하지만 위 함수들은 내가 지금 당면해 있는 문제를 해결하기에는 적절치 않았다.
하여... 사용했던 방법들은 아래와 같다.
#1. 처음에 짰던 방법....
SELECT M.KEY, M.TYPE, S.A_VALUE, 0 AS B_VALUE
FROM MAIN_TABLE M
, SUB_TABLE_A S
WHERE M.KEY = B.KEY
AND REPLACE(M.TYPE, 'B', '') = S.TYPE
AND M.TYPE = 'AB'
UNION ALL
SELECT M.KEY, M.TYPE, 0 AS S.A_VALUE, B_VALUE
FROM MAIN_TABLE M
, SUB_TABLE_B S
WHERE M.KEY = B.KEY
AND REPLACE(M.TYPE, 'A', '') = S.TYPE
AND M.TYPE = 'AB'
--> 이렇게 조회하면 아래와 같이 나올 것이다.
KEY TYPE A_VALUE B_VALUE
1 AB 10 0
1 AB 0 20
2 AB 30 0
2 AB 0 40
--> 이것을 SUM 과 PARTITION BY , GROU PBY 를 하면..
SELECT A.KEY, SUM(A_VALUE) OVER(PARTITION BY A.KEY) AS A_VALUE, SUM(B_VALUE) OVER(PARTITION BY A.KEY) AS B_VALUE
FROM (
SELECT M.KEY, M.TYPE, S.A_VALUE, 0 AS B_VALUE
FROM MAIN_TABLE M
, SUB_TABLE_A S
WHERE M.KEY = B.KEY
AND REPLACE(M.TYPE, 'B', '') = S.TYPE
AND M.TYPE = 'AB'
UNION ALL
SELECT M.KEY, M.TYPE, 0 AS S.A_VALUE, B_VALUE
FROM MAIN_TABLE M
, SUB_TABLE_B S
WHERE M.KEY = B.KEY
AND REPLACE(M.TYPE, 'A', '') = S.TYPE
AND M.TYPE = 'AB'
) A GROUP BY A.KEY, A_VALUE, B_VALUE;
--> 결과는....
KEY TYPE A_VALUE B_VALUE
1 AB 10 20
1 AB 10 20
2 AB 30 40
2 AB 40 40
--> 이것을 다시 GROUP BY 하게 되면...
SELECT B.KEY, B.A_VALUE, B.B_VALUE
FROM (
SELECT A.KEY, SUM(A_VALUE) OVER(PARTITION BY A.KEY) AS A_VALUE, SUM(B_VALUE) OVER(PARTITION BY A.KEY) AS B_VALUE
FROM (
SELECT M.KEY, M.TYPE, S.A_VALUE, 0 AS B_VALUE
FROM MAIN_TABLE M
, SUB_TABLE_A S
WHERE M.KEY = B.KEY
AND REPLACE(M.TYPE, 'B', '') = S.TYPE
AND M.TYPE = 'AB'
UNION ALL
SELECT M.KEY, M.TYPE, 0 AS S.A_VALUE, B_VALUE
FROM MAIN_TABLE M
, SUB_TABLE_B S
WHERE M.KEY = B.KEY
AND REPLACE(M.TYPE, 'A', '') = S.TYPE
AND M.TYPE = 'AB'
) A GROUP BY A.KEY, A_VALUE, B_VALUE
) B GROUP BY B.KEY, B.A_VALUE, B.B_VALUE
--> 결과는....
KEY TYPE A_VALUE B_VALUE
1 AB 10 20
2 AB 30 40
#2. WITH 를 사용한 방법
WITH RESULT_A AS (
SELECT M.KEY, S.A_VALUE
FROM MAIN_TABLE M
, SUB_TABLE_A S
WHERE M.KEY = B.KEY
AND REPLACE(M.TYPE, 'B', '') = S.TYPE
AND M.TYPE = 'AB'
), RESULT_B AS (
SELECT M.KEY, S.B_VALUE
FROM MAIN_TABLE M
, SUB_TABLE_B S
WHERE M.KEY = B.KEY
AND REPLACE(M.TYPE, 'A', '') = S.TYPE
AND M.TYPE = 'AB'
)
SELECT A.KEY, A.A_VALUE, B.B_VALUE
FROM RESULT_A A
, RESULT_B B
WHERE A.KEY = B.KEY;
--> 결과
KEY TYPE A_VALUE B_VALUE
1 AB 10 20
2 AB 30 40
.... WITH 를 사용하니 훨씬 간단해졌다.
만약 데이터가 두 테이블 중에 없을 수도 있다면 JOIN 으로 인해 결과가 정상적으로 나오지 않을 수도 있으므로,
OUTER JOIN 정도는 걸어 주는것도 좋겠다. (어느 테이블에서 데이터가 없는지 모른다면 FULL OUTER JOIN 을 걸던...)
'프로그래밍' 카테고리의 다른 글
[MySQL or MariaDB] 인덱스 관련 정리 (0) | 2019.11.20 |
---|---|
Proxy 를 사용한 Apache + IIS 동일 포트 사용 및 멀티도메인 처리 (Forward Proxy, Reverse Proxy) (0) | 2019.08.23 |
Spring MVC + Swagger2 (7) | 2019.06.23 |
[ASP] SendXMLHttp 사용과 Timeout (0) | 2018.12.24 |
[MySQL] explicit_defaults_for_timestamp (root 비밀번호 찾기 시) (0) | 2018.10.16 |
- Total
- Today
- Yesterday
- 족발
- 빈트후크
- 성계 투어
- 우유니
- 칼라마
- Oracle
- 쿠스코
- calama
- Uyuni
- 볼리비아
- 남미 저가항공
- 후마리
- 푸에르토 나탈레스
- 킹덤 호텔
- 토레스 델 파이네
- 나미비아
- 남미
- 마추피추
- Cambodia
- 햄버거
- aguas calientes
- 성스러운 계곡
- 빅토리아폴스
- Namibia
- Cusco
- 애드센스
- 캄보디아
- jQuery
- 아구아스 칼리엔테스
- 칠레
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |