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
운영게시판
최근게시물
Oracle Q&A 40480 게시물 읽기
No. 40480
고난이도 쿼리 질문2
작성자
디비사랑
작성일
2014-05-30 11:35
조회수
6,981

지난번 귀한답변 주셨는데 실제 데이터패턴은 좀 다양한 상황이라서 다시금 고수님들의 자문좀 구해보겠습니다.

 
SELECT 1 work_id, 'start' gbn, to_date('2014-01-02','YYYY-MM-DD') work_dt FROM dual UNION ALL
 
SELECT 1 work_id, 'end' gbn, to_date('2014-01-03','YYYY-MM-DD') work_dt FROM dual UNION ALL
 
SELECT 20 work_id, 'start' gbn, to_date('2014-01-05','YYYY-MM-DD') work_dt FROM dual UNION ALL
 
SELECT 21 work_id, 'start' gbn, to_date('2014-01-09','YYYY-MM-DD') work_dt FROM dual UNION ALL
 
SELECT 30 work_id, 'start' gbn, to_date('2014-01-15','YYYY-MM-DD') work_dt FROM dual UNION ALL
 
SELECT 30 work_id, 'start' gbn, to_date('2014-01-16','YYYY-MM-DD') work_dt FROM dual UNION ALL
 
SELECT 30 work_id, 'end' gbn, to_date('2014-01-17','YYYY-MM-DD') work_dt FROM dual
 
로직은 시작일과 종료일별 일자간격을 구하는것인데
 
문제는 위데이이터에서 work_id가 30이고 start가 연달아 이어질때 첫행만 취해야하는것입니다.
 
시작일기준 : gbn의 값이 'start'이고
 
종료일기준1 :이전행의 work_id동일하고 gbn값이 'end'
 
종료일기준2 :이전행의 work_id가 다르고 gbn값이 'start'
 
원하는 결과는 아래와 같습니다.
 
start_dt *********** end_dt *********** term 2014-01-02 ******* 2014-01-03 ******* 1 
2014-01-05 ******* 2014-01-09 ******* 4 
2014-01-09 ******* 2014-01-15 ******* 6 
2014-01-15 ******* 2014-01-17 ******* 2
자체 해결했을때 서브쿼리를 두번사용하다보니 성능에 심각한 문제가 있어서 자문을 다시 구해보겠습니다. 
아래는 자체 해결한 방식입니다.
with t as (…) 
select work_id, start_dt, end_dt, gbn
From
(
      Select work_id, gbn, work_dt start_dt,
           Lead(work_dt) over (order by work_dt) end_dt
      From
      (
            Select work_id, work_dt, gbn
            From
            (
                   Select work_id, work_dt, gbn,
                   Lag(work_id,1,99) over(order by work_dt) pre_work_id, lag(gbn,1,'x') over(order by work_dt) pre_gbn
                  From t
         )
        Where work_id!=pre_work_id or ( work_id=pre_work_id and gbn!=pre_gbn)
)
)
Where gbn='start'
이 글에 대한 댓글이 총 2건 있습니다.

SELECT work_id
     , MIN(work_dt) start_dt
     , NVL( MAX(DECODE(gbn, 'end', work_dt))
          , LEAD(MIN(work_dt)) OVER(ORDER BY MIN(work_dt))
          ) AS end_dt
  FROM t
 GROUP BY work_id
;

마농(manon94)님이 2014-05-30 15:25에 작성한 댓글입니다.

 귀한의견 주셔서 감사합니다. 항상 많이 배웁니다.

디비사랑님이 2014-05-30 16:09에 작성한 댓글입니다. Edit
[Top]
No.
제목
작성자
작성일
조회
40483분석함수 lead 사용쿼리 문의 [4]
디비사랑
2014-06-03
7391
40482mview log에 생성되는 데이터를 mview에 한해 제한할 수 있는지요.
이차승
2014-06-02
6732
40481https://localhost:1158/em 이 안됩니다.
김성환
2014-05-30
8528
40480고난이도 쿼리 질문2 [2]
디비사랑
2014-05-30
6981
40479Oracle 과 MSSQLserver 메모리 사용할때 관련 질문
채미남
2014-05-29
6411
40478고난이도 쿼리 질문 [1]
디비사랑
2014-05-28
6904
40477쿼리 질문 [2]
초보
2014-05-28
6451
Valid XHTML 1.0!
All about the DATABASE... Copyleft 1999-2024 DSN, All rights reserved.
작업시간: 0.017초, 이곳 서비스는
	PostgreSQL v16.2로 자료를 관리합니다