0

我在 Oracle 11g 数据库中有一个类似于以下内容的表:

process_times:
--------------------------------------------
machine_id | load_id | start_time | end_time

一些示例记录可能如下所示:

process_times:
----------------------------------------------------------------
machine_id | load_id | start_time          | end_time
----------------------------------------------------------------
220        | 25      | 06/24/2012 04:29:00 | 06/25/2012 04:42:38
187        | 23      | 06/22/2012 14:41:00 | 06/24/2012 00:34:32
187        | 18      | 06/20/2012 11:57:00 | 06/20/2012 23:53:51

我正在尝试编写一个查询,该查询将返回一个与表示每台机器负载之间的停机时间的属性的关系。停机时间是指给定机器的每个 end_time 和以下 start_time 之间的时间。

因此,对于上面的示例,我会得到如下结果:

result:
----------------------
machine_id | down_time
----------------------
220        |  0
187        |  (06/22/2012 14:41:00 - 06/20/2012 23:53:51) -- the actual result, I wrote it like this to be more clear

下午的大部分时间我一直在修补这个问题,这只是我真正想要写的查询的先决条件,所以我想我会发帖看看是否有人有任何指示让我走向正确方向。

编辑我应该提到的另一个限制是我需要让结果列出每台机器的单独停机时间,而不仅仅是给定时间段内的停机时间总量。

4

2 回答 2

2

有趣的问题。您需要首先获取上一个/下一个记录,然后进行减法。幸运的是,Oracle 对此具有领先/滞后功能。

所以:

select machine_id, (lastend - start_time) as down_time
from (select pt.*,
             lag(end_time, 1) over (partition by machine_id order by end_time) as lastend
      from process_time pt
     ) pt
where lastend is not null

这会找到之前的记录和结束时间,然后计算停机时间。

于 2012-06-25T19:47:42.167 回答
1

这未经测试,但根据我的评论,这可以让您获得正常运行时间。如果您知道总时间窗口,则停机时间很容易从正常运行时间得出。

SELECT machine_id, SUM(joblen) AS uptime
FROM (
    SELECT machine_id, (end_time - start_time) AS joblen
    FROM process_times
    )
GROUP BY machine_id

事实上,子查询甚至可能不是必需的,你可以做类似的事情

SELECT machine_id, SUM(end_time - start_time) AS uptime
FROM process_times
GROUP BY machine_id

不过我不知道。

从那里,您可能会执行以下操作:

SELECT machine_id, (lifetime - uptime) AS downtime
FROM (
    SELECT machine_id, 
        SUM(end_time - start_time) AS uptime, 
        (min(start_time) - max(end_time) as lifetime
    FROM process_times
    GROUP BY machine_id
    )

无论如何,这是我如何处理它的粗略轮廓,它几乎肯定不会是剪切和粘贴式的答案。

于 2012-06-25T19:54:01.950 回答