2013-03-26 2 views
2

다음과 같은 Oracle 11.2 테이블이 있습니다.Oracle SQL 그룹 메시지 간격

MSG_ID JOB_ID STATUS CREATION_DATE 
1  101 SUB  03/30/2011 14:39:52 
2  101 SUB  03/30/2011 14:44:37 
3  101 RCVD  03/31/2011 14:41:49 
4  101 ACCPTD 03/31/2011 14:59:51 
5  101 DESIGN 03/31/2011 17:44:37 
6  101 REVIEW 03/31/2011 17:44:50 
7  101 (null) 04/01/2011 07:51:41 
8  101 REJECTED 04/01/2011 07:56:56 
9  101 (null) 04/01/2011 16:36:19 
10  101 REVIEW 04/01/2011 16:43:49 
11  101 APPROVED 04/04/2011 07:55:45 
12  101 (null) 04/04/2011 08:14:23 
13  101 REJECTED 04/04/2011 14:46:17 
14  101 REVIEW 04/04/2011 14:50:50 
15  101 (null) 04/04/2011 14:51:27 
16  101 REVIEW 04/04/2011 14:57:50 
17  101 (null) 04/04/2011 15:34:50 
18  101 APPROVED 04/04/2011 15:41:21 
19  101 (null) 04/04/2011 15:41:23 
20  101 REJECTED 04/04/2011 15:41:24 
21  101 REVIEW 04/04/2011 16:07:52 
22  101 (null) 04/05/2011 08:50:35 
23  101 APPROVED 04/05/2011 10:54:51 
24  101 PROD  04/05/2011 11:08:50 
25  101 COMPLET 04/06/2011 20:09:49 

고유 한 상태 조합 간의 메시지 상태 및 시간 간격을 인접한 (생성 날짜와 관련하여) 그룹화하려고합니다. Null 상태는 무시할 수 있습니다. 결과는 다음과 같습니다.

JOB_ID FROM_STATUS TO_STATUS TIME_INTERVAL 
101 SUB   RCVD  sum of time intervals 
101 RCVD  ACCPTD sum of time intervals 
101 ACCPTD  DESIGN sum of time intervals 
101 DESIGN  REVIEW sum of time intervals 
101 REVIEW  REJECTED sum of time intervals 
101 REJECTED REVIEW sum of time intervals 
101 REVIEW  APPROVED sum of time intervals 
101 APPROVED REJECTED sum of time intervals 
101 APPROVED PROD  sum of time intervals 
101 PROD  COMPLETE sum of time intervals 

누군가가이 작업에 필요한 SQL을 도울 수 있습니까?

고맙습니다.

+1

여러 레코드가 있습니다. 작업 ID 101에는 상태가 sub 인 2 개의 레코드가 있습니다. 어느 쪽을 사용 하시겠습니까? –

+1

@Joe. . . 시간 간격의 합은 어떻게 정의합니까? –

+0

@Dan, 인접한 dups의 경우 하위와 마찬가지로 가장 초기의 dup을 사용하고 싶습니다. – Joe

답변

3

이것은 갭 - 아일랜드 문제의 변형입니다. 첫 번째 단계는 like this을 할 수있는 연속적인 그룹을 식별하는 것입니다 :

select msg_id, job_id, status, creation_date, 
    row_number() over (partition by job_id order by creation_date) 
     - row_number() over (partition by job_id, status 
      order by creation_date) as chain 
from t42 
where status is not null 

... 당신 같은 job_idstatus 값을 각 블록에 대해 고유 한 '체인'수를 제공한다. 그런 다음 각각의 '체인'에 대해 단일 행을 얻기 위해 해당 링크를 접을 수 있습니다. 연속 된 각 상태 블록에 대해 가장 빠른 creation_date에만 관심이있는 것으로 보입니다 (제 생각 엔).

lead을 사용하면 다음 블록을 들여다 보며 시차를 해결할 수 있습니다. 마지막으로 '최종 합계'요구 사항을 이해하면 간격을 그룹화합니다. 그래서 모두

: 제공하면 데이터와

select job_id, from_status, to_status, sum(time_interval) as time_interval 
from (
    select job_id, status as from_status, status_start, 
     lead(status) over (partition by job_id order by status_start) 
      as to_status, 
     lead(status_start) over (partition by job_id order by status_start) 
      - status_start as time_interval 
    from (
     select distinct job_id, status, chain, 
      min(creation_date) over (partition by job_id, status, chain 
       order by chain) as status_start 
     from (
      select msg_id, job_id, status, creation_date, 
       row_number() over (partition by job_id order by creation_date) 
        - row_number() over (partition by job_id, status 
         order by creation_date) as chain 
      from t42 
      where status is not null 
     ) 
    ) 
) 
where to_status is not null 
group by job_id, from_status, to_status 
order by job_id, min(status_start); 

:

JOB_ID FROM_STA TO_STATU TIME_INTERVAL 
---------- -------- -------- ------------- 
     101 SUB  RCVD  1.00135417 
     101 RCVD  ACCPTD  .012523148 
     101 ACCPTD DESIGN  .114421296 
     101 DESIGN REVIEW  .000150463 
     101 REVIEW REJECTED .591736111 
     101 REJECTED REVIEW  .387430556 
     101 REVIEW APPROVED 3.45099537 
     101 APPROVED REJECTED .285127315 
     101 APPROVED PROD  .009710648 
     101 PROD  COMPLET  1.37568287 

10 rows selected. 

time_interval는 일이지만, 당신이 원하는 그러나 것을 조작 할 수 있습니다; 간격을 언급 했으므로 Oracle 간격을 사용할 수 있습니다.

select job_id, from_status, to_status, 
    numtodsinterval(sum(time_interval) , 'DAY') as time_interval 
from (
... 

    JOB_ID FROM_STA TO_STATU TIME_INTERVAL 
---------- -------- -------- ----------------------------- 
     101 SUB  RCVD  +000000001 00:01:57.000000000 
     101 RCVD  ACCPTD +000000000 00:18:02.000000000 
     101 ACCPTD DESIGN +000000000 02:44:46.000000000 
     101 DESIGN REVIEW +000000000 00:00:13.000000000 
     101 REVIEW REJECTED +000000000 14:12:06.000000000 
     101 REJECTED REVIEW +000000000 09:17:54.000000000 
     101 REVIEW APPROVED +000000003 10:49:26.000000000 
     101 APPROVED REJECTED +000000000 06:50:35.000000000 
     101 APPROVED PROD  +000000000 00:13:59.000000000 
     101 PROD  COMPLET +000000001 09:00:59.000000000 

10 rows selected. 
+0

+1, 아주 좋은 대답 – DCookie

+0

@Alex, 아주 좋은 대답 참으로. 나는 그것을 되 살리고 있지만, 지금까지 내가 필요로하는 것이 정확히 보인다. 고맙습니다. – Joe

+0

@Alex, 당신의 대답은 저에게 완벽하게 작용했습니다. 다시 감사합니다. – Joe