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
운영게시판
최근게시물
DB2 Q&A 864 게시물 읽기
No. 864
쿼리문 질문입니다...ㅡㅡ^
작성자
김종진
작성일
2005-10-23 13:41ⓒ
2005-10-23 13:45ⓜ
조회수
7,182

3일째 이문제 하나 가지고 머리 쥐어 뜯고 있습니다.
이게 해결되야 다른 업무에 적용해서 계속 진행되는데...흠...ㅡㅡ^
아래와 같은 테이블이 하나 있습니다.

테이블 명은 TEST

CODE CODE_NAME LEV START_A START_B END_A END_B
---------------------------------------------------------

1001 AAA-1 10 81 1 99 4
1001 AAA-2 10 81 2 99 4
1001 AAA-3 10 81 3 99 4
1001 AAA-4 10 81 4 99 4
1001 AAA-5 10 82 2 99 4
1001 AAA-6 10 82 4 99 4
2001 BBB-1 20 82 1 99 4
2001 BBB-2 20 80 4 99 4
3001 CCC-1 30 83 3 99 4
3001 CCC-2 30 82 2 99 4


PK 는 CODE,START_A,START_B 입니다.


즉 위3개가 조합해서 하나의 PK가 되는 것입니다.


START_A는 1~99의 값을 가지고 START_B는 1-4의 값을 가집니다.


즉, START_A는 어떤 프로젝트의 시작 번호이고 START_B는 분기를 나타냅니다.

 

검색 조건은 START_A, START_B입니다.


예를 들어 START_A 가 81 이고 START_B가 2 이면 각각의 CODE에서

제일 가깝거나 같은 값들이 하나식 출력하게 만드는 겁니다.
즉 현재 입력받은 값(START_A와START_B)들의 같거나 최근 과거 값들을 출력하고

해당 CODE에 과거의 값들이 없으면 그 CODE는 출력 하지 않습니다.


즉 START_A가 81이고 START_B가 2일 경우 출력 값은

 

CODE CODE_NAME LEV START_A START_B END_A END_B
-----------------------------------------------------------------------

1001 AAA-2 10 81 2 99 4
2001 BBB-2 20 80 4 99 4

위와 같이 출력 되게 하는것입니다

 

1001 코드는 81, 2에 해당되는 코드가 있어서 출력 되었고
2001 코드는 가장 가까운 80, 4가 출력 되었고
3001 코드는 81, 2 보다 작은 값들이 없으므로 출력 되지 않았습니다.

 

먼저 입력 받은 START_A 값보다 같거나 작은 값들의 최대 값들의 집합을 구하고
그 집합 안에서 입력 받은 START_B 보다 같거나 작은 최대값을 구해야 하는데
만약 START_B에 같거나 최대값이 없으면 START_A의 최대값보다 적은 값에서

값을 찾아야 합니다.

무슨 말인고 하니 입력 받은 값이 81과 3 인데 만약 4001 코드 값엔

80,4 와 81,4 가 있으면 80,4 가 출력 되게 해야 한다는 것인데 제가 짠 쿼리문은

자꾸 81,4를 출력 합니다...ㅡㅡ^


즉 이경우는 START_A의 최대값의 집합에서 값을 찾다보니 이런 출력이 나오는데
이거 어떻게 해결 할 방법 없는지요...
다른 분의 도움으로 오라클의 LPAD 함수를 사용하여 아래와 같이 해결했는데

문제는 제가 사용하는 디비가 DB2라서 오라클에서 지원하는 함수와 틀리다는 것입니다.

DB2에서는 이 문제를 어떻게 해결해야 하는지...
-------------------------------------------------------------------------

SELECT code, code_name, lev, start_a, start_b, end_a, end_b

FROM (SELECT a.*,

ROW_NUMBER() OVER(PARTITION BY code

ORDER BY start_a DESC, start_b DESC) no

FROM TEST a

WHERE LPAD(a.start_a,2,'0') || a.start_b

<= LPAD(:asStart_a,2,'0') || :asStart_b

)

WHERE no = 1



 

이 글에 대한 댓글이 총 3건 있습니다.
SELECT a.code, a.code_name, a.lev, a.start_a, a.start_b, a.end_a, a.end_b
  FROM test a
 where a.start_a <= :as_start_a
   and a.start_b <= :as_start_b
   and a.start_a * 10 + a.start_b
       = ( select max(b.start_a * 10 + b.start_b)
             from test b
            where b.start_a <= :as_start_a
              and b.start_b <= :as_start_b )

start_a 와 start_b 가 숫자 필드라면... 이렇게 해보세요.
임명순(a3sd)님이 2005-10-24 09:08에 작성한 댓글입니다.

db2에는 오라클에서 지원하는 lpad,rpad함수가 없습니다.

꼭 필요하시면 UDF(사용자정의함수)를 생성해서 사용하셔야 합니다.

 

예)

CREATE FUNCTION LPAD (C1 VarChar(4000), N integer, C2 VarChar(4000))
 RETURNS VARCHAR(4000)
 LANGUAGE SQL
 SPECIFIC LPADBase
 DETERMINISTIC
 CONTAINS SQL
 NO EXTERNAL ACTION
 RETURN
 CASE
   WHEN N > length(C1) THEN substr(repeat(C2,(N-length(C1)+length(C2))/(length(C2)+1-sign(length(C2)))),1,N-length(C1)) || C1
   ELSE substr(C1,1,N)
 END
;
---------------------------------------------------
DB20000I The SQL command completed successfully.
 
 
--------------------------------------------------------------------------
SELECT char(lpad('ABCDE',15,'*.'),50) FROM SYSIBM.SYSDUMMY1;
---------------------------------------------------
 
1                                                 
--------------------------------------------------
*.*.*.*.*.ABCDE                                   
 
    1 record(s) selected.
 
 
 
--------------------------------------------------------------------------
SELECT char(lpad('ABCDE',3,'*.'),50) FROM SYSIBM.SYSDUMMY1;
---------------------------------------------------
 
1                                                 
--------------------------------------------------
ABC                                               
 
    1 record(s) selected.
 
 
 
--------------------------------------------------------------------------
SELECT char(lpad('ABCDE',15,'') || 'X',50) FROM SYSIBM.SYSDUMMY1;
---------------------------------------------------
 
1                                                 
--------------------------------------------------
          ABCDEX                                  
 
    1 record(s) selected.

 

위의 쿼리는 이렇게 써도 될것 같은데요 ^^

 

select d.code, d.code_name, d.lev, d.start_a, d.start_b, d.end_a, d.end_b
from (
select c.*,
row_number() over(partition by c.code order by c.start_a DESC, c.start_b DESC) no
from (
select * from test a where a.start_a <= :asStart_a
except
select * from test b where b.start_a = :asStart_a  and b.start_b > :asStart_b  ) as c
) as d
where d.no = 1 ;

 

 


김동주님이 2005-10-24 14:56에 작성한 댓글입니다. Edit

정말 감사합니다.

임명순님과 김동주 님의 글이 많은 도움이 되었습니다.

환절기 건강 조심하시고 행복하세요~^^*

김종진님이 2005-10-25 01:03에 작성한 댓글입니다. Edit
[Top]
No.
제목
작성자
작성일
조회
867JDBC로 DB2접속이 않됩니다. [3]
이상식
2005-10-27
10184
866인스턴스가 Shutdown 되었을때 트랩파일이 떨어지지 않는다?
dbman
2005-10-26
5187
865솔라리에서 pkgadd로 DB2설치 방법? [1]
db2man
2005-10-24
5393
864쿼리문 질문입니다...ㅡㅡ^ [3]
김종진
2005-10-23
7182
863DB2 의 데이터를 개행 하는 방법은 ??? [4]
자바왕
2005-10-22
8131
862db2 agent가 latch(latchDirtyPoolsEntry)를 물고있다라는 의미? [2]
db2man
2005-10-21
6353
859다음 sql문장 관련 질문입니다. [2]
궁금이
2005-10-20
5733
Valid XHTML 1.0!
All about the DATABASE... Copyleft 1999-2024 DSN, All rights reserved.
작업시간: 0.019초, 이곳 서비스는
	PostgreSQL v16.2로 자료를 관리합니다