반복연결(Loop Query)
Declare Cursor 를 통해 기준 테이블을 하나씩 Fetch 한 다음 거기서 얻은 상수값을 For Loop 에서 다시 연결하는 SQL을 수행하는 방법.
조인(Nested Loops)과 반복연결(Loop Query) 방식의 비교
{section}
{column:width=20}
조인처리
SELECT a.fld1, ....., a.fldn
, b.col1, ....., b.coln
FROM tab2 b, tab1 a
WHERE a.key1 = b.key2
AND a.fld1 = '10'
ORDER BY a.fld2
;
{column}
{column:width=20}
반복연결
DECLARE
CURSOR cur1 IS
SELECT a.fld1, ....., a.fldn
FROM tab1 a
WHERE a.fld1 = '10'
ORDER BY a.fld2
;
BEGIN
FOR a IN cur1 LOOP
SELECT b.col1, ....., b.coln
FROM tab2 b
WHERE b.key2 = a.key1
;
END LOOP;
END;
/
{column}
{column:width=20}
인라인뷰
SELECT a.fld1, ....., a.fldn
, b.col1, ....., b.coln
FROM tab2 b
, (SELECT a.fld1, ....., a.fldn
FROM tab1 a
WHERE a.fld1 = '10'
ORDER BY a.fld2
) a
WHERE a.key1 = b.key2
;
{column}
{column:width=40}
{column}
{section}
1) 조인 후 정렬하는 쿼리
2) 우선 a 를 정렬 한 후 b를 반복적으로 읽어오도록 변경한 쿼리
3) 인라인뷰를 이용한 조인쿼리
{section}
{column:width=20}
조인처리
SELECT b.부서명
, SUM(a.매출액) 매출액
FROM tab1 a, tab2 b
WHERE a.부서코드 = b.부서코드
AND a.매출일 LIKE '200503%'
GROUP BY b.부서명
;
{column}
{column:width=20}
반복연결
DECLARE
CURSOR cur1 IS
SELECT a.부서코드
, SUM(a.매출액) 매출액
FROM tab1 a
WHERE a.매출일 LIKE '200503%'
GROUP BY a.부서코드
;
BEGIN
FOR a IN cur1 LOOP
SELECT b.부서명
FROM tab2 b
WHERE b.부서코드 = a.부서코드
;
END LOOP;
END;
/
{column}
{column:width=20}
인라인뷰
SELECT b.부서명
, a.매출액
FROM (SELECT a.부서코드
, SUM(a.매출액) 매출액
FROM tab1 a
WHERE a.매출일 LIKE '200503%'
GROUP BY a.부서코드
) a
, tab2 b
WHERE WHERE b.부서코드 = a.부서코드
;
{column}
{column:width=40}
{column}
{section}
1) 조인 후 집계(Group By)하는 쿼리
2) 우선 a 를 Group By 한 후 b를 반복적으로 읽어오도록 변경한 쿼리
3) 인라인뷰를 이용한 조인쿼리
{section}
{column:width=20}
조인처리
SELECT a.*
, DECODE(a.입출고구분, '1', b.거래처명
, '2', c.공정명
, '3', d.창고명 ) 입출고처명
FROM 입출정보 a
, 거래처 b
, 공정 c
, 창고 d
WHERE a.입출일자 LIKE '200503%'
AND b.거래처코드(+) = DECODE(a.입출고구분, '1', a.입출고처코드)
AND c.공정코드 (+) = DECODE(a.입출고구분, '2', a.입출고처코드)
AND d.창고코드 (+) = DECODE(a.입출고구분, '3', a.입출고처코드)
;
스칼라서브쿼리
SELECT a.*
, DECODE(a.입출고구분
, '1', (SELECT b.거래처명 FROM 거래처 b WHERE b.거래처코드 = a.입출고처코드)
, '2', (SELECT c.공정명 FROM 공정 c WHERE c.공정코드 = a.입출고처코드)
, '3', (SELECT d.창고명 FROM 창고 d WHERE d.창고코드 = a.입출고처코드)
) 입출고처명
FROM 입출정보 a
WHERE a.입출일자 LIKE '200503%'
;
{column}
{column:width=20}
반복연결
DECLARE
CURSOR cur1 IS
SELECT a.*
FROM 입출정보 a
WHERE a.입출일자 LIKE '200503%'
;
BEGIN
FOR a IN cur1 LOOP
IF a.입출고구분 = '1' THEN
SELECT b.거래처명
FROM 거래처 b
WHERE b.거래처코드 = a.입출고처코드
;
ELSIF a.입출고구분 = '2' THEN
SELECT c.공정명
FROM 공정 c
WHERE c.공정코드 = a.입출고처코드
;
ELSIF a.입출고구분 = '3' THEN
SELECT d.창고명
FROM 창고 d
WHERE d.창고코드 = a.입출고처코드
;
END IF;
END LOOP;
END;
/
{column}
{column:width=20}
{column}
{column:width=40}
{column}
{section}
1) 연관된 모든 테이블을 아우터 조인
3) 스칼라서브쿼리를 이용한 조인쿼리
부분범위로 수행되는 SQL은 주어진 처리범위가 아무리 크더라도 매우 빠른 수행속도를 얻을 수 있다.
조인(Nested Loops)과 반복연결(Loop Query) 방식의 비교
비교 | 조인(One SQL) | 반복연결(Loop Query) |
---|---|---|
컬럼가공 | SQL 내에서 조인된 테이블의 모든 컬럼을 마음대로 가공 | 별도의 언어를 통해 어플리케이션 내에서 추가적인 가공 |
병렬처리 | SQL 단위로 병렬처리 가능 | Loop 내에서는 병렬처리 포기 |
튜닝 | 엑세스 경로를 변경해 준다거나 조인방법을 바꾸는 등 간단하게 수행속도를 향상시킬 수 있다. | 엑세스 경로 를 바꾸려면 코딩을 다시 해야 함 |
코딩 | SQL만 약간 고쳐주면 된다. | SQL 및 별도의 언어도 함께 수정되어야 하며 코딩량도 많다. |