database.sarang.net
UserID
Passwd
Database
DBMS
MySQL
ㆍPostgreSQL
Firebird
Oracle
Informix
Sybase
MS-SQL
DB2
Cache
CUBRID
LDAP
ALTIBASE
Tibero
DB 문서들
스터디
Community
공지사항
자유게시판
구인|구직
DSN 갤러리
도움주신분들
Admin
운영게시판
최근게시물
PostgreSQL Q&A 6774 게시물 읽기
No. 6774
ORACLE 의 CONNECT BY PRIOR 와 같은 역할...
작성자
궁금
작성일
2006-07-11 18:30
조회수
9,095

안녕하세요.

 

ORACLE 의 CONNECT BY PRIOR 와 같은 역할을 할수 있는게 postgreSQL 에도 있을까 해서 질문 올립니다.

 

function 을 사용하는 방식을 얼핏 본것 같습니다만...정확하게 어떤 방식으로 어떻게 처리를 해야되는지를 모르겠습니다.

 

그리고 그 방법 외에는 없는것인지도 궁금합니다...

 

답변 부탁드립니다....

이 글에 대한 댓글이 총 1건 있습니다.

현존하는 RDBMS에서 Recursive Query를 가장 완벽하게 구현하는 것은 단연 오라클입니다.
자동자 생산공정과 같이 BOM구조를 구현해야 하는 시스템에서 오라클을 선호하는 이유가 바로 이 때문이고, 그것을 가능하게 한 것이 바로 connect by start with 구문입니다.

물론 DB나 SQLServer2005와 같은 타 DB에서 With(...)라는 구문을 제공하기는 하지만 내부적으로 Inline View를 생성하여 그 View와 Join을 하는 형태로 순환구조를 풀어나가기 때문에 개인적인(?) 생각으로는 순환구조에서만큼은 오라클이 훨씬 막강하다고 생각합니다.

그렇다면 PostgreSQL에서는 순환구조를 어떻게 풀어나가야 할까요?
그것은 말씀하신 것처럼 connectby()라는 함수를 이용하는 방법 밖에 없습니다.
하지만 사용해 보시면 아시겠지만 답답함을 많이 느끼실 겁니다. 즉, connect by start with과 같은 구현은 잊어버리시는 것이 좋을 겁니다. ㅡ.ㅡ
더욱 아쉬운 건 이 함수는 Default로 설치되는 것이 아니라 Optional이라는 점입니다.
자세한 내용을 여기서 다 언급하기는 힘들 것 같구요. 여기서는 함수의 설치방법과 사용법을 간단하게 말씀드리겠습니다.

1. 설치법
(1) 리눅스 시스템이라면 POSRTGRESQLHOME/contrib(예:/usr/local/src/postgresql-8.1.3/contrib) 로 이동합니다. 
(여기에 README라는 파일이 있는데 자세한 내용은 이 폴더에 있는 이러한 텍스트 파일을 참조하시기 바랍니다.)
(2) make
(3) make install
(4) psql -U postgres database_name < tablefunc.sql

2. 사용법
Syntax를 요약하면 대략 다음과 같습니다.
(parameter_set에 따라 도출할 수 있는 결과물에 달라질 수 있으니 자세한 것은 README 파일을 참조하세요.)
-----------------------------------------------------------------------------
SELECT column1[,column2 ...] 
FROM connectby(parameter_set)
AS return_table_name (return_column_name data_type[,return_column_name data_type])

- parameter_set
parameter1: '참조할 테이블 명 또는 뷰명' -> 문자열
parameter2: '컬럼명1' -> 문자열
parameter3: '컬럼명2' -> 문자열
parameter4: '시작값' -> 문자열
parameter5: 시작 위치의 레벨 ->숫자 int형
parameter6: 분리문자 -> 한문자
-----------------------------------------------------------------------------
Syntax만 봐서는 알기 힘든 것 같습니다.
그럼 예를 하나 들어 보겠습니다.

먼저 아래와 같은 테이블을 생성하고 데이터를 입력하겠습니다.

CREATE TABLE connectby_tree(keyid text, parent_keyid text, pos int);

INSERT INTO connectby_tree VALUES('row1',NULL, 0);
INSERT INTO connectby_tree VALUES('row2','row1', 0);
INSERT INTO connectby_tree VALUES('row3','row1', 0);
INSERT INTO connectby_tree VALUES('row4','row2', 1);
INSERT INTO connectby_tree VALUES('row5','row2', 0);
INSERT INTO connectby_tree VALUES('row6','row4', 0);
INSERT INTO connectby_tree VALUES('row7','row3', 0);
INSERT INTO connectby_tree VALUES('row8','row6', 0);
INSERT INTO connectby_tree VALUES('row9','row5', 0);


그럼 지금부터 row2로 부터 그 하위에 있는 순환관계 구조를 풀어보기 위해서 다음과 같은 SQL을 작성하겠습니다.

SELECT * FROM connectby('connectby_tree', 'keyid', 'parent_keyid', 'row2', 0, ',')
 AS t(keyid text, parent_keyid text, level int, branch text);

이 SQL을 간단히 설명하겠습니다.
먼저 connectby() 괄호 안에 있는 parameter_set을 설명드리자면,

첫번째 파라미터인 'connectby_tree'는 위에서 언급한 것 처럼 테이블이나 뷰명이 됩니다.
유의하실 점은 여기에 SQL문에 들어갈 수 없다는 것입니다.
예를 들어 'select * from connectby_tree where pos = 1' 와 같은 SQL문장이 들어갈 수 없습니다.

두번째 파라미터와 세번째 파라미터는 계층질의에서 상위계층(부모)와 하위계층(자식)의 관계를 규정하는 컬럼들입니다.
오라클의 예를 들어 설명드리자면 CONNECT BY PRIOR empno = mgr에서 CONNECT BY PRIOR에 해당된다고 보시면 됩니다.
즉, 두번째 파라미터 'keyid'는 위에서 empno 세번째 파라미터 'parent_keyid'는 mgr에 해당됩니다. 

네번째 파라미터 'row2'는 계층 질의의 루트(부모)로 사용될 행을 지정합니다.
다시 한 번 오라클의 예를 들자면 START WITH job= 'PRESIDENT' 에서 'PRESIDENT'라고 생각하시면 됩니다. 단 오라클에서는 서브쿼리를 사용할 수 있지만 이 파라미터에 서브쿼리가 들어갈 수 없습니다. 비단 이 파라미터 뿐만 아니라 모든 파라미터에서 그러합니다.

다섯번째 파라미터 0 는 루트 계층의 레벨입니다. 즉 최상위 계층은 0. 그 다음 계층은 1...이런 식으로 계층 레벨이 표시됩니다.

여섯번째 파라미터 ','는 divide문자열입니다. 이는 아래의 위 쿼리의 실행결과를 보면 금방 알 수 있을 것입니다.

다음으로 AS이하의 절을 보도록 하죠. 
먼저, AS t에서 t는 리턴되는 테이블 명입니다. 
즉 결과는 t라는 이름의 테이블로 리턴을 하며 그 테이블은 괄호 안에 있는 형식으로 리턴이 된다는 것입니다.
여기서 유의 하실 것은 리턴 되는 컬럼 이름은 사용자가 마음대로 지정할 수 있으나 리턴형은 반드시 text와 레벨의 경우는 int라는 점입니다. 이것은 당연한 것이겠죠. 함수를 그렇게 만들었으니까요....
자세한 것은 이는 이 함수를 만드는데 사용되었던 tablefunc.sql 파일을 열어보시기 바랍니다.

그럼 결과를 보도록 하죠.

keyid        parenet_keyid        level        branch
-------   ----------------  -------  ---------------------
row2        Null                         0             row2
row4        row2                       1             row2,row4
row6        row4                       2             row2,row4,row6
row8        row6                       3             row2,row4,row6,row8
row5        row2                       1             row2,row5
row9        row5                       2             row2,row5,row9

제가 알고 있는 한도 내에서 답변을 드렸는데 혹시 틀린 내용이 있으시면 말씀해 주세요.
그럼 수고하세요.

디비디비딕(teggy)님이 2006-08-20 05:13에 작성한 댓글입니다.
[Top]
No.
제목
작성자
작성일
조회
67772개의 칼럼값을 변환하여 하나의 칼럼에 넣는 쿼리문? [1]
루믹서
2006-07-12
3178
6776[질문]이런 쿼리문이 가능할까요. [1]
도와주세요
2006-07-12
3312
6775효과적인 JOIN 과 INDEX 생성에 대하여 [8]
입문자
2006-07-12
5055
6774ORACLE 의 CONNECT BY PRIOR 와 같은 역할... [1]
궁금
2006-07-11
9095
6773로그파일을 open 할수없다네요 정말 돌겠 습니다. [1]
권태수
2006-07-11
3733
6772[답변] 권태수님 또 답변입니다.
이상원
2006-07-11
3550
6771timestamp의 값 '1000-02-29 01:00:00.0'으로 검색실패 [2]
chol
2006-07-10
4461
Valid XHTML 1.0!
All about the DATABASE... Copyleft 1999-2024 DSN, All rights reserved.
작업시간: 0.036초, 이곳 서비스는
	PostgreSQL v16.2로 자료를 관리합니다