我需要帮助计算进程间的停机时间。它需要按IMPORTID分组,然后按IMPORTREQUESTID分组。 IMPORTREQUESTID对应于IMPORTID请求中的不同阶段。因此,例如在下面的数据集中,我需要我的SQL查询在IMPORTREQUESTID中找到最高或最新 ENDDATE,然后从中减去STARTDATE(最低)的下一行或者更确切地说下一组IMPORTREQUESTID的最小值(STARTDATE)。我已经对查询进行了排序,以降序排列IMPORT ID和IMPORTREQUEST ID。我应该使用“CONNECT BY”吗?在IMPORTREQUESTID的下一个直接行或集群中,在IMPORTID和IMPORTREQUESTID行中分组并找到最高ENDDATE然后从中减去最低STARTDATE的最佳方法是什么?基本上,我试图计算过程完成和下一个过程开始之间的间隔时间。有关样本数据,请参见下表:
IMPORTID IMPORTREQUESTID STARTDATE ENDDATE
1156 63833 4/23/2017 18:18 4/23/2017 18:18
1156 63833 4/23/2017 18:18 4/23/2017 18:18
1156 63832 4/23/2017 17:56 4/23/2017 17:57
1156 63832 4/23/2017 17:56 4/23/2017 17:57
1156 63832 4/23/2017 17:56 4/23/2017 17:57
预期结果:上述查询将返回给我的整个行集获得的所有差异的总和,最后显示每个IMPORTID:
ImportID TOTAL Downtime
1156 21 mins
或更好:
详细分解每个唯一的IMPORTREQUESTID(上行的结束行和下行的开始日期)之间的间隔(以秒为单位),并返回以下唯一行(相的最大ENDDATE和下一阶段的前进min(startdate)) ):
IMPORTID IMPORTREQUESTID STARTDATE ENDDATE DIFF
1156 63833 4/23/2017 18:18 4/23/2017 18:18 21 mins
1156 63832 4/23/2017 17:56 4/23/2017 17:57
答案 0 :(得分:0)
这样的东西?我还没有完全理解这个问题..特别是61秒来自我得到21分钟。我也不知道你为什么在你的例子中重复数据....所以我使用distinct删除了它。
这里有两个要点。
1)LEAD是一个窗口函数,它让我们可以预览定义的顺序序列中的下一条记录。我们也可以“PARTITION”,这样除非ImportId和ImportRequestID匹配,否则每个系列都不会向前看
Round((EndDate-LEAD(EndDate) over (order by ImportID, ImportRequestID DESC))*60*24)
会成为
Round((EndDate-LEAD(EndDate) over (PARTITION BY IMPORTID order by ImportRequestID DESC))*60*24)
2)我使用distinct来消除看似重复的记录;但我怀疑你的数据集确实有重复,所以可能不需要它;或者你的连接不完整会导致重复。
With CTE (IMPORTID, ImportRequestID, StartDate, EndDate) as (
SELECT 1156, 63833, to_date('4/23/2017 18:18','MM/DD/YYYY HH24:MI'), to_date('4/23/2017 18:18','MM/DD/YYYY HH24:MI') FROM DUAL UNION ALL
SELECT 1156, 63833, to_date('4/23/2017 18:18','MM/DD/YYYY HH24:MI'), to_date('4/23/2017 18:18','MM/DD/YYYY HH24:MI') FROM DUAL UNION ALL
SELECT 1156, 63832, to_date('4/23/2017 17:56','MM/DD/YYYY HH24:MI'), to_date('4/23/2017 17:57','MM/DD/YYYY HH24:MI') FROM DUAL UNION ALL
SELECT 1156, 63832, to_date('4/23/2017 17:56','MM/DD/YYYY HH24:MI'), to_date('4/23/2017 17:57','MM/DD/YYYY HH24:MI') FROM DUAL UNION ALL
SELECT 1156, 63832, to_date('4/23/2017 17:56','MM/DD/YYYY HH24:MI'), to_date('4/23/2017 17:57','MM/DD/YYYY HH24:MI') FROM DUAL)
SELECT ImportID
, ImportRequestID
, to_char(StartDate,'MM/DD/YYYY HH24:MI') StartDate
, to_char(EndDate,'MM/DD/YYYY HH24:MI') EndDate
, Round((EndDate-LEAD(EndDate) over (order by ImportID, ImportRequestID DESC))*60*24) as Minutediff
FROM (SELECT DISTINCT ImportID
, ImportRequestID
, StartDate
, EndDate
From CTE) B
答案 1 :(得分:0)
您可以通过importid和importrequestid对数据进行排序,以确保它们按照正确的时间顺序排列。然后如xQbert所述,使用lead()或lag()为结束日期时间和下一个进程的开始日期时间创建列。
lag(enddate, 1) over (order by importrequestid) as priorend
然后使用类似下面的函数来查找差异。
create or replace function timestamp_diff_in_seconds (ts1 in timestamp, ts2 in timestamp)
return number is total_secs number;
diff interval day(9) to second(6);
begin
diff := ts2 - ts1;
total_secs := abs(extract(second from diff) + extract(minute from diff)*60 + extract(hour from diff)*60*60 + extract(day from diff)*24*60*60);
return total_secs;
end timestamp_diff_in_seconds;
然后调用函数示例...
select timestamp_diff_in_seconds(priorend, startdate) as downtime.