2013-03-26 3 views
2

У меня есть таблица Oracle 11.2, которая выглядит следующим образом.Периодические сообщения Oracle SQL group

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 

Я пытаюсь группировать смежные (по дате создания даты) статусы сообщений и промежуток времени между каждой уникальной комбинацией состояний. Нулевые статусы можно игнорировать. Результат будет выглядеть следующим образом.

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

У вас есть несколько записей. Идентификатор задания 101 имеет 2 записи со статусом sub. Какой из них вы хотите использовать? –

+1

@Joe. , , Как вы определяете сумму временных интервалов? –

+0

@ Dan, для смежных дубликатов, как и sub, я хочу использовать самый ранний 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_id и status значением. Затем вы можете свернуть их, чтобы получить одну строку для каждой «цепи», так как вам кажется, что вас интересует самый ранний 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

Смежные вопросы