cross tab query는 rows를 columns로 바꾸는 query임.
(PIVOT)
1. 모듈설치
PostgreSQL에서는 함수를 통해서 구현할 수 있으며,
해당 함수를 사용하기 위해선 tablefunc 모듈을 설치해야 함.
[설치법]
* 가정
- 소스 컴파일 방식으로 설치
- 소스 압축 풀린 경로 : /usr/local/src/postgresql-8.4.3
1. 모듈 경로로 이동
cd /usr/local/src/postgresql-8.4.3/contrib/tablefunc
2. 컴파일&설치
make
make install
3. 함수추가
// 컴파일 하고 나면 모듈 디렉토리에 tablefunc.sql 파일이 생김.
// 그 안에 함수추가에 필요한 query들이 들어 있음.
// 원하는 놈으로 취사선택 해서 설치할 것.
// 본인은 아래정도의 함수를 추가함.
SET search_path TO pg_catalog;
CREATE OR REPLACE FUNCTION normal_rand(int4, float8, float8)
RETURNS setof float8
AS '$libdir/tablefunc','normal_rand'
LANGUAGE C VOLATILE STRICT;
ALTER FUNCTION normal_rand(integer, double precision, double precision) OWNER TO postgres;
CREATE OR REPLACE FUNCTION crosstab(text)
RETURNS setof record
AS '$libdir/tablefunc','crosstab'
LANGUAGE C STABLE STRICT;
ALTER FUNCTION crosstab(text) OWNER TO postgres;
CREATE OR REPLACE FUNCTION crosstab(text,int)
RETURNS setof record
AS '$libdir/tablefunc','crosstab'
LANGUAGE C STABLE STRICT;
ALTER FUNCTION crosstab(text,int) OWNER TO postgres;
CREATE OR REPLACE FUNCTION crosstab(text,text)
RETURNS setof record
AS '$libdir/tablefunc','crosstab_hash'
LANGUAGE C STABLE STRICT;
ALTER FUNCTION crosstab(text,text) OWNER TO postgres;
CREATE OR REPLACE FUNCTION connectby(text,text,text,text,int,text)
RETURNS setof record
AS '$libdir/tablefunc','connectby_text'
LANGUAGE C STABLE STRICT;
ALTER FUNCTION connectby(text,text,text,text,int,text) OWNER TO postgres;
CREATE OR REPLACE FUNCTION connectby(text,text,text,text,int)
RETURNS setof record
AS '$libdir/tablefunc','connectby_text'
LANGUAGE C STABLE STRICT;
ALTER FUNCTION connectby(text,text,text,text,int) OWNER TO postgres;
cd /usr/local/src/postgresql-8.4.3/contrib/tablefunc
2. 컴파일&설치
make
make install
3. 함수추가
// 컴파일 하고 나면 모듈 디렉토리에 tablefunc.sql 파일이 생김.
// 그 안에 함수추가에 필요한 query들이 들어 있음.
// 원하는 놈으로 취사선택 해서 설치할 것.
// 본인은 아래정도의 함수를 추가함.
SET search_path TO pg_catalog;
CREATE OR REPLACE FUNCTION normal_rand(int4, float8, float8)
RETURNS setof float8
AS '$libdir/tablefunc','normal_rand'
LANGUAGE C VOLATILE STRICT;
ALTER FUNCTION normal_rand(integer, double precision, double precision) OWNER TO postgres;
CREATE OR REPLACE FUNCTION crosstab(text)
RETURNS setof record
AS '$libdir/tablefunc','crosstab'
LANGUAGE C STABLE STRICT;
ALTER FUNCTION crosstab(text) OWNER TO postgres;
CREATE OR REPLACE FUNCTION crosstab(text,int)
RETURNS setof record
AS '$libdir/tablefunc','crosstab'
LANGUAGE C STABLE STRICT;
ALTER FUNCTION crosstab(text,int) OWNER TO postgres;
CREATE OR REPLACE FUNCTION crosstab(text,text)
RETURNS setof record
AS '$libdir/tablefunc','crosstab_hash'
LANGUAGE C STABLE STRICT;
ALTER FUNCTION crosstab(text,text) OWNER TO postgres;
CREATE OR REPLACE FUNCTION connectby(text,text,text,text,int,text)
RETURNS setof record
AS '$libdir/tablefunc','connectby_text'
LANGUAGE C STABLE STRICT;
ALTER FUNCTION connectby(text,text,text,text,int,text) OWNER TO postgres;
CREATE OR REPLACE FUNCTION connectby(text,text,text,text,int)
RETURNS setof record
AS '$libdir/tablefunc','connectby_text'
LANGUAGE C STABLE STRICT;
ALTER FUNCTION connectby(text,text,text,text,int) OWNER TO postgres;
2. crosstab() 함수로 pivot 구현
'공장' 테이블과 '분기별 작업진행률' 테이블이 두개가 있다고 치고,
한 번의 query로 공장별-분기별 작업진행률을 가져오려고 한다고 가정.
공장
create table plant (idx int, name text);
insert into plant values (1, '제1공장');
insert into plant values (2, '제2공장');
분기별 작업진행률
create table proc (idx int, lv text, pp int);
insert into proc values (1, '1분기', 33);
insert into proc values (2, '2분기', 52);
insert into proc values (3, '3분기', 77);
insert into proc values (4, '4분기', 89);
insert into proc values (5, '1분기', 11);
insert into proc values (6, '2분기', 27);
insert into proc values (7, '3분기', 45);
insert into proc values (8, '4분기', 99);
1. ANSI-SQL 이용
아래의 query로 가져와서 분기별로 쪼개서 사용해야 함.
SELECT
DISTINCT ON (a.name, b.idx, b.lv)
a.name as "공장명", b.lv as "분기", b.pp||'%' as "진행률"
FROM plant as a, proc as b
WHERE a.idx=b.idx
ORDER BY b.idx, b.lv;
DISTINCT ON (a.name, b.idx, b.lv)
a.name as "공장명", b.lv as "분기", b.pp||'%' as "진행률"
FROM plant as a, proc as b
WHERE a.idx=b.idx
ORDER BY b.idx, b.lv;
결과)
공장명 | 분기 | 진행률
----------+-------+--------
제1공장 | 1분기 | 33%
제1공장 | 2분기 | 52%
제1공장 | 3분기 | 77%
제1공장 | 4분기 | 89%
제2공장 | 1분기 | 11%
제2공장 | 2분기 | 27%
제2공장 | 3분기 | 45%
제2공장 | 4분기 | 99%
2. crosstabI() 함수 이용
아래의 query로 한방에 가져올 수 있음.
SELECT
a.name as "공장명",
b.p1||'%' as "1분기 진행률",
b.p2||'%' as "2분기 진행률",
b.p3||'%' as "3분기 진행률",
b.p4||'%' as "4분기 진행률"
FROM
plant as a,
(select * from
crosstab('select * from proc order by 1,2')
as ct(p_idx int, p1 int, p2 int, p3 int, p4 int)) as b
WHERE a.idx=b.p_idx;
a.name as "공장명",
b.p1||'%' as "1분기 진행률",
b.p2||'%' as "2분기 진행률",
b.p3||'%' as "3분기 진행률",
b.p4||'%' as "4분기 진행률"
FROM
plant as a,
(select * from
crosstab('select * from proc order by 1,2')
as ct(p_idx int, p1 int, p2 int, p3 int, p4 int)) as b
WHERE a.idx=b.p_idx;
결과)
공장명 | 1분기 진행률 | 2분기 진행률 | 3분기 진행률 | 4분기 진행률
-----------+--------------+---------------+--------------+--------------
제1공장 | 33% | 52% | 77% | 89%
제2공장 | 11% | 27% | 45% | 99%
참고
http://www.postgresql.org/docs/8.4/static/tablefunc.html
'DataBase' 카테고리의 다른 글
[MySQL] 사용자 DB 생성 (0) | 2010.11.12 |
---|---|
[PostgreSQL] 조건식 (0) | 2010.04.09 |
[PostgreSQL] Date/Time Functions and Operators (0) | 2010.03.29 |
[PostgreSQL] pgcrypto 설치 (0) | 2010.03.19 |
[PostgreSQL] enum type (0) | 2010.03.15 |