重复集上的Oracle时差

时间:2015-05-27 15:01:36

标签: oracle plsql

我确信这是一个很容易解决的问题,但是无论我怎么看,我都看不出它是怎么回事。

我正在使用Oracle数据库,我正在尝试报告处理时间。系统正在运行一个进程,该进程将传入的文件和进程接收到数据库中。在执行此任务时,它会记录每个不同部分的发生时间以及来自哪个部分。我已经过滤了数据,只是给我开始和结束时间,因为这是我目前感兴趣的。示例数据

integer(c_int) function cudaMalloc(devPtr, size) bind(C,name="cudaMalloc")
  use iso_c_binding
  type(c_ptr) :: devPtr
  integer(c_size_t), value :: size
end function

我想要得到的是每个"套装的持续时间" (开始时间到结束时间)。当一天只有一次出现时很容易,但是当看到像16日这样的日子,在一天中有两套,或者从19日开始到20日结束时,我正在努力。我知道这在编程语言中是可能的,但我相信在Oracle中也必须是可能的。

我希望从上面得到的输出是:

5   15/MAY/15 00:37:01  Started
5   15/MAY/15 00:50:45  Finished
5   16/MAY/15 02:07:41  Started
5   16/MAY/15 02:19:16  Finished
5   16/MAY/15 23:20:25  Started
5   16/MAY/15 23:28:53  Finished
5   17/MAY/15 23:16:36  Started
5   17/MAY/15 23:27:51  Finished
5   18/MAY/15 23:31:28  Started
5   18/MAY/15 23:47:41  Finished
5   19/MAY/15 23:44:12  Started
5   20/MAY/15 00:06:17  Finished
5   20/MAY/15 23:33:42  Started
5   20/MAY/15 23:58:16  Finished

谢谢,

2 个答案:

答案 0 :(得分:3)

正如Patrick Bacon在评论中提到的那样,您可以使用前导和滞后analytic functions来查看每一行的前后。如果您正在查看的行是“已启动”,那么您需要在下一行(按时间顺序,对于相同的源)达到峰值,以使用lead获取匹配的“已完成”行。相反,如果您正在查看的行是“已完成”,那么您需要在上一行达到峰值,以使用lag获得匹配的“已启动”行:

    select distinct source,
      case when action = 'Started' then time
        else lag(time) over (partition by source order by time) end as starttime,
      case when action = 'Finished' then time
        else lead(time) over (partition by source order by time) end as endtime
    from t
    order by source, starttime;

    SOURCE STARTTIME           ENDTIME           
---------- ------------------- -------------------
         5 2015-05-15 00:37:01 2015-05-15 00:50:45
         5 2015-05-16 02:07:41 2015-05-16 02:19:16
         5 2015-05-16 23:20:25 2015-05-16 23:28:53
         5 2015-05-17 23:16:36 2015-05-17 23:27:51
         5 2015-05-18 23:31:28 2015-05-18 23:47:41
         5 2015-05-19 23:44:12 2015-05-20 00:06:17
         5 2015-05-20 23:33:42 2015-05-20 23:58:16

因为你正在寻找前后,你最终会得到重复的数据对;在这里,我使用distinct来压缩这些重复项,但您也可以将其用作子查询并过滤结果。

带有CTE的

SQL Fiddle可提供您的样本数据。

答案 1 :(得分:2)

功能lead()的解决方案:

select tsource, starttime, endtime
  from (
    select tsource, ttime starttime, status,
        lead(ttime) over (partition by tsource order by ttime) endtime 
      from test)
  where status = 'Started'

SQLFiddle

编辑: 如果可能发生两行,其状态为已启动,并且之间没有已完成 那么你需要一些防止这种情况的保护,例如这显示为null:

select tsource, starttime, endtime
  from (
    select tsource, ttime starttime, status,
        case when lead(status) over (partition by tsource order by ttime) = 'Finished'
          then lead(ttime) over (partition by tsource order by ttime)  
          else null
        end endtime
      from test)
  where status = 'Started'