Oracle

게시글 보기
작성자 유건데이타 등록일 2015-05-16
제목 행을 열로 SELECT 하기
행을 열로 SELECT 하기
===============================


1. 사용자 요구

다음과 같은 테이블이 있다고 가정하자.

P_no LOC
---------------
a a-1
a a-2
a a-3
b b-1
b b-2
b b-3
b b-4
c c-1
c c-2
c c-3
c c-4
c c-5
-------------


이런 정보를 다음과 같은 형태로 보길 원한다.

P_No LOC1 LOC2 LOC3 LOC4 LOC5
-----------------------------------------------
a a-1 a-2 a-3
b b-1 b-2 b-3 b-4
c c-1 c-2 c-3 c-4 c-5



2. 처리 방법.

1) Package 생성

일련 번호를 부여해 주는 다음과 같은 package를 만든다.

** Package Spec
create or replace package GROUPING as
function serial_no(Current_token varchar2) return number;
pragma restrict_references(serial_no, WNDS);
end GROUPING;
/

** Package Body
create or replace package body GROUPING as
Previous_no number := 0;
Previous_token varchar2(100) := '';
function serial_no(Current_token varchar2) return number is
begin
if (Current_token = Previous_token) then
Previous_no := Previous_no + 1;
else
Previous_no := 0;
end if;
Previous_token := Current_token ;
return(Previous_no);
end serial_no;
end GROUPING;
/


이 Package를 이용하면 다음과 같은 형태로 볼 수 있다.
select --+ NO_MERGE
p_no, loc, grouping.serial_no(p_no) x
from Tab1
group by p_no, loc

P_no Loc X
--------------------
a a-1 0
a a-2 1
a a-3 2
b b-1 0
b b-2 1
b b-3 2
b b-4 3
c c-1 0
c c-2 1
c c-3 2
c c-4 3
c c-5 4
--------------------

2) SQL의 구성
다음과 같은 SQL을 수행하면 원하는 결과를 가져올 수 있다.
select p_no, max(l1) LOC1, max(l2) LOC2, max(l3) LOC3, max(l4) LOC4, max(l5)
LOC5
from (
select p_no, loc,
decode(x, '0', loc) l1,
decode(x, '1', loc) l2,
decode(x, '2', loc) l3,
decode(x, '3', loc) l4,
decode(x, '4', loc) l5
from (
select --+ NO_MERGE
p_no, loc, grouping.serial_no(p_no) x
from a
group by p_no, loc
)
)
group by p_no



3. 참고 사항

위에 제시된 SQL의 key point는 NO_MERGE라는 HINT의 사용이다.
이 함수는 In-line View에 있는 내용을 먼저 수행하도록 하여
임의의 테이블을 메모리 상에 만들어 두는 역할을 한다.

이 HINT가 없는 경우에는 각 decode 문장에서 grouping.serial_no(p_no)를
한번씩 Call하기 때문에 의도와 전혀 다른 결과를 가져온다.
그러나 이 HINT를 사용함으로써 반복된 grouping.serial_no(p_no) 호출 없이
SQL이 원하는 순서대로 수행되며, Performance의 입장에서도 타당한 방식으로
수행하는 것이 된다.
Comment
등록된 코멘트가 없습니다.