Oracle SQL查询逻辑 - 基于日期差异分组

时间:2016-04-03 00:26:05

标签: sql oracle oracle11g group-by

有人可以帮助实现下述要求的想法:

enter image description here

上面的表格(截图中)维护了计划流程的作业历史记录。

我的要求是让目标表按照以下屏幕截图维护累积历史记录。

enter image description here

请参阅下面的源/目标表结构和源样本记录sql代码:

CREATE TABLE "XHQ"."SHIFT_LOG" ("SEQUENCE_ID" NUMBER(10,0), 
"JOB_ID" NUMBER(10,0), 
"START_TS" DATE, 
"END_TS" DATE, 
"MINIMUM_VALUE" FLOAT(126), 
"MAXIMUM_VALUE" FLOAT(126), 
"AVERAGE_VALUE" FLOAT(126), 
"USERID" NVARCHAR2(80) );

Insert into XHQ.SHIFT_LOG (SEQUENCE_ID,JOB_ID,START_TS,END_TS,MINIMUM_VALUE,MAXIMUM_VALUE,AVERAGE_VALUE,USERID) values (10908,12000,to_date('01-MAY-15','DD-MON-RR'),null,null,null,null,'admin');
Insert into XHQ.SHIFT_LOG (SEQUENCE_ID,JOB_ID,START_TS,END_TS,MINIMUM_VALUE,MAXIMUM_VALUE,AVERAGE_VALUE,USERID) values (10825,12000,to_date('29-APR-15','DD-MON-RR'),to_date('01-MAY-15','DD-MON-RR'),null,null,null,'admin');
Insert into XHQ.SHIFT_LOG (SEQUENCE_ID,JOB_ID,START_TS,END_TS,MINIMUM_VALUE,MAXIMUM_VALUE,AVERAGE_VALUE,USERID) values (10800,12000,to_date('29-APR-15','DD-MON-RR'),to_date('29-APR-15','DD-MON-RR'),5,10,7.5,'admin');
Insert into XHQ.SHIFT_LOG (SEQUENCE_ID,JOB_ID,START_TS,END_TS,MINIMUM_VALUE,MAXIMUM_VALUE,AVERAGE_VALUE,USERID) values (10725,10500,to_date('28-APR-15','DD-MON-RR'),to_date('29-APR-15','DD-MON-RR'),4,8,6,'admin');
Insert into XHQ.SHIFT_LOG (SEQUENCE_ID,JOB_ID,START_TS,END_TS,MINIMUM_VALUE,MAXIMUM_VALUE,AVERAGE_VALUE,USERID) values (10625,10500,to_date('27-APR-15','DD-MON-RR'),to_date('27-APR-15','DD-MON-RR'),6,6,6,'admin');
Insert into XHQ.SHIFT_LOG (SEQUENCE_ID,JOB_ID,START_TS,END_TS,MINIMUM_VALUE,MAXIMUM_VALUE,AVERAGE_VALUE,USERID) values (10620,10500,to_date('23-APR-15','DD-MON-RR'),to_date('27-APR-15','DD-MON-RR'),null,null,null,'admin');
Insert into XHQ.SHIFT_LOG (SEQUENCE_ID,JOB_ID,START_TS,END_TS,MINIMUM_VALUE,MAXIMUM_VALUE,AVERAGE_VALUE,USERID) values (10525,10500,to_date('22-APR-15','DD-MON-RR'),to_date('23-APR-15','DD-MON-RR'),null,null,null,'admin');
Insert into XHQ.SHIFT_LOG (SEQUENCE_ID,JOB_ID,START_TS,END_TS,MINIMUM_VALUE,MAXIMUM_VALUE,AVERAGE_VALUE,USERID) values (10510,10500,to_date('18-APR-15','DD-MON-RR'),to_date('20-APR-15','DD-MON-RR'),8,16,8,'admin');

让我概述一下这项要求。

考虑JobID = 10500

  • 按顺序:10510,它已于18-apr开始运行至20-apr。一旦成功完成,它将获得与其对应的min,max,avg值作为摘要。

  • 但是如果我们考虑序列号:10525,它从22-apr开始,一直运行到23-apr。然而,由于一些网络中断,它在中间停留了几分钟并重新开始。因为它有min,max,avg值为NULL,因为作业不完整。它又在27日发布了另一个网络问题,因此它被停止并再次恢复。最后在27号apr(序列号:10625),它成功完成,并为其分配了最小值,最大值,平均值。

enter image description here

在这种情况下,属于序列id 10625,10620和10525的记录条目需要被视为单个组,并且来自序列id 10525的start_ts需要被分配给sequenceid 10625,如下所示

enter image description here

上述情况的一个例外是,如果end_ts为null(序列号:10908)(它表示当前活动的作业)。

enter image description here

此处分组应为序列ID:10825,输出应如下图所示。

enter image description here

如果您需要任何澄清,请与我们联系。

提前感谢您的时间和宝贵的建议。

1 个答案:

答案 0 :(得分:2)

尝试:

SELECT sequence_id, job_id, new_start_ts as start_ts, end_ts,
       minimum_value, maximum_value, average_value, userid
FROM (
    SELECT t.*,
           min( start_ts ) over ( partition by job_id, new_seq_id ) As new_start_ts
    FROM (
          SELECT t.* ,
                 first_value( case when minimum_value is not null then sequence_id end IGNORE NULLS )
                 over (partition by job_id order by sequence_id rows between current row and unbounded following ) as new_seq_id
          FROM SHIFT_LOG t
    ) t
)
WHERE minimum_value IS NOT NULL 
  OR new_seq_id IS NULL AND end_ts IS NULL
ORDER BY sequence_id desc;