如何根据一天中的任务完成从给定日期列获取开始日期和结束日期(oracle)

时间:2017-08-02 06:34:57

标签: sql oracle

在虚拟数据中,您可以看到有两列 Task_Completion Time_stamp 。每当任务完成时都会运行一个java调度程序,例如,scheduler在 15-FEB-2016 上运行5次,在 17-FEB 上运行所以我想要一个从给定列计算start_time和end_time的查询 time_stamp < /强>

Task_Completion                     Time_stamp
true                     15-FEB-16 11.37.56.013000000 AM
true                     15-FEB-16 11.42.55.593000000 AM
true                     15-FEB-16 11.47.48.970000000 AM
true                     15-FEB-16 12.21.57.587000000 PM
true                     15-FEB-16 12.26.55.767000000 PM 
true                     17-FEB-16 10.24.03.320000000 PM
true                     18-FEB-16 10.19.04.333000000 PM

所以输出必须像

       start_time                                      end_time
15-FEB-16 11.37.56.013000000 AM          15-FEB-16 11.47.48.970000000 AM
15-FEB-16 12.21.57.587000000 PM          15-FEB-16 12.26.55.767000000 PM 
17-FEB-16 10.21.33.320000000 PM          17-FEB-16 10.26.33.320000000 PM
18-FEB-16 10.16.33.333000000 PM          18-FEB-16 10.21.33.333000000 PM

有两个条件

条件1。如果 time_stamp 中存在 0-5min 缺口,例如 15-Feb 那么 start_time 11.37.56.013000000 end_time 11.47.48.970000000 但是如果没有,那么检查当天是否有任何计划如 15-Feb 在12.21.57.587000000(start_time)和12.26.55.767000000(end_time)

condition2。如果计划一天只运行一次,那么从那时起平均 time_stamp 并添加/ sub 2.30 min (即)无需再次检查

例如

17-Feb 10.21.33.320000000(start_time) 10.26.33.320000000(end_time)与18-Feb相同

所以我的逻辑是,做一个条件1和条件2的联合,这就是我最终的结果......

--------------------condition2-------------------

select count(*), min(time_stamp) - interval '150' second start_date, max(time_stamp) + interval '150' second end_date
from serverstatus 
group by to_char(time_stamp,'dd-mon-yy')
having count(*)=1
UNION ALL

------------condition1 query--------------------------

我需要Condition1查询

1 个答案:

答案 0 :(得分:1)

SELECT start_time - CASE num_grp_per_day
                      WHEN 1
                      THEN INTERVAL '150' SECOND
                      ELSE INTERVAL '0' SECOND
                    END AS start_time,
       end_time   + CASE num_grp_per_day
                      WHEN 1
                      THEN INTERVAL '150' SECOND
                      ELSE INTERVAL '0' SECOND
                    END AS end_time
FROM   (
  SELECT DISTINCT
         MIN( time_stamp ) OVER ( PARTITION BY grp ) AS start_time,
         MAX( time_stamp ) OVER ( PARTITION BY grp ) AS end_time,
         COUNT( DISTINCT grp ) OVER ( PARTITION BY TRUNC( time_stamp ) ) AS num_grp_per_day
  FROM   (
    SELECT time_stamp,
           SUM( diff ) OVER ( ORDER BY time_stamp ) AS grp
    FROM   (
      SELECT time_stamp,
             CASE
               WHEN time_stamp - LAG( time_stamp ) OVER ( ORDER BY time_stamp )
                      <= INTERVAL '5' MINUTE
               THEN 0
               ELSE 1
             END AS diff
      FROM   your_table
    )
  )
)
ORDER BY start_time;

或者,如果您只想将所有零宽度组扩展到5分钟间隔(而不仅仅是每天有一个),那么:

SELECT MIN( time_stamp ) - CASE COUNT(*)
                             WHEN 1
                             THEN INTERVAL '150' SECOND
                             ELSE INTERVAL '0' SECOND
                           END AS start_time,
       MAX( time_stamp ) + CASE COUNT(*)
                             WHEN 1
                             THEN INTERVAL '150' SECOND
                             ELSE INTERVAL '0' SECOND
                           END AS end_time
FROM   (
  SELECT time_stamp,
         SUM( diff ) OVER ( ORDER BY time_stamp ) AS grp
  FROM   (
    SELECT time_stamp,
           CASE
             WHEN time_stamp - LAG( time_stamp ) OVER ( ORDER BY time_stamp )
                    <= INTERVAL '5' MINUTE
             THEN 0
             ELSE 1
           END AS diff
    FROM   your_table
  )
)
GROUP BY grp;