【问题标题】:How can I subtract two row's values within DIFFERENT columns using SQL如何使用 SQL 减去 DIFFERENT 列中的两行值
【发布时间】:2017-04-27 18:23:43
【问题描述】:

我需要帮助计算进程之间的停机时间。它需要按 IMPORTID 分组,然后按 IMPORTREQUESTID 分组。 IMPORTREQUESTID 对应于 IMPORTID 请求中的不同阶段。因此,例如在下面的数据集中,我需要我的 SQL 查询在 IMPORTREQUESTID 中找到 highestLatest ENDDATE,然后从中减去下一行的 STARTDATE(最低),或者更确切地说IMPORTREQUESTID 的下一个集群的 min(STARTDATE)。我已经对查询进行了排序,以便按降序对 IMPORT ID 和 IMPORTREQUEST ID 进行排序。我应该使用“连接方式”吗?在 IMPORTID 和 IMPORTREQUESTID 的行中分组并找到最高 ENDDATE 的最佳方法是什么,然后在 IMPORTREQUESTID 的下一个直接行或集群中从中减去最低的 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 和下一阶段的最小(开始日期) ):

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

【问题讨论】:

  • 是的,对不起。我正在使用关系数据库管理。 MySQL 或 Oracle 数据库中的系统。我在 Oracle 数据库上使用 SQL 查询。或者更确切地说,在 Oracle 服务器上运行 SQL 来获取信息。
  • 预期的结果是什么?我认为这将有助于澄清你的问题。所以你想看看 63833 4/23/2017 18:18 和 63832 4/23/2017 17:57 之间的区别?领先/滞后可能会有所帮助。
  • 我重新编辑了描述或问题,得到了预期的结果。抱歉,我是新手,不知道如何让表格正确显示。
  • 您只需使用 {} 图标来表示代码块以获得更好的表格格式。
  • 我很困惑,差别不是大约 21 分钟吗?不是 61 秒?

标签: oracle group-by max min connect-by


【解决方案1】:

这样的?我还没有完全理解这个问题..特别是 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

【讨论】:

    【解决方案2】:

    您可以按 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.
    

    【讨论】:

      猜你喜欢
      • 2016-05-08
      • 2018-03-22
      • 1970-01-01
      • 1970-01-01
      • 2021-12-16
      • 2017-03-04
      • 2018-04-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多