【问题标题】:find the elapsed time between two dates in oracle sql在oracle sql中查找两个日期之间经过的时间
【发布时间】:2014-02-01 12:52:08
【问题描述】:

我需要以 hh:mm:ss 格式查找时间之间的差异

select msglog.id,max(msglog.timestamp) enddate,
   min(msglog.timestamp) startdate,
   enddate - startdate
   from MESSAGELOG msglog
   group by id

在上面的查询中,msglog.timestamp 的类型是 DATE。

如何在 oracle 中以正确格式获取经过时间或时间之间的差异?

【问题讨论】:

    标签: sql oracle date-arithmetic


    【解决方案1】:

    Oracle 中的日期算术产生一个以天数表示的数字。因此,要转换为小时,您将乘以 24,然后乘以 trunc 以获得整数:

    trunc(24 * (enddate - startdate))
    

    要获取分钟,请将天数转换为分钟,mod() 转换为 60:

    mod(trunc(24 * 60 * (enddate - startdate)), 60)
    

    对于秒,再次将天转换为秒,mod() 将其转换为 60:

    mod(trunc(24 * 60 * 60 * (enddate - startdate)), 60)
    

    现在你可以把这些放在一起得到你需要的字符串值。

    【讨论】:

    • 感谢@GriffeyDog 的支持,并为您自己+1!你的回答也会很好用。它归结为大量数学与大量函数调用,我希望有些人可能更喜欢大量数学。
    【解决方案2】:

    当您减去两个 DATE 值(如 enddate - startdate)时,您会得到以小数为单位的天数差异,因此例如 1.5 表示 1 1/2 天或 36 小时。您可以使用大量数学将其转换为HH:MI:SS,但更简单的方法是使用NUMTODSINTERVAL 函数将十进制值转换为INTERVAL DAY TO SECOND 值:

      NUMTODSINTERVAL(enddate - startdate, 'DAY')
    

    您可能认为TO_CHAR 函数可以将其格式化为HH:MI:SS,但它似乎并不能那样工作。您可以改用EXTRACTTO_CHAR 来确保获得前导零:

     TO_CHAR(EXTRACT(HOUR FROM NUMTODSINTERVAL(enddate-startdate, 'DAY')), 'FM00')
       || ':' ||
     TO_CHAR(EXTRACT(MINUTE FROM NUMTODSINTERVAL(enddate-startdate, 'DAY')), 'FM00')
       || ':' ||
     TO_CHAR(EXTRACT(SECOND FROM NUMTODSINTERVAL(enddate-startdate, 'DAY')), 'FM00')
    

    格式代码的00 部分指定两位数字,如果需要,可以使用前导零。 FM 部分去掉了格式化结果中的前导空格,如果需要,该空格是为负号保留的。

    另请注意,您的查询获取聚合值并在同一个SELECT 列表中使用它们。 Oracle 不会让你这样做。试试这样的:

    WITH StartEndByID AS (
      SELECT
        msglog.id,
        NUMTODSINTERVAL(max(msglog.timestamp) - min(msglog.timestamp), 'DAY') elapsed
      FROM messagelog msglog
      GROUP BY id
    )
    SELECT
      id,
      TO_CHAR(EXTRACT(HOUR FROM elapsed), 'FM00') || ':' ||
        TO_CHAR(EXTRACT(MINUTE FROM elapsed), 'FM00') || ':' ||
        TO_CHAR(EXTRACT(SECOND FROM elapsed), 'FM00') AS ElapsedHHMISS
    FROM StartEndByID
    

    【讨论】:

    • 我比我的回答更喜欢这个,+1。
    • 您好 Ed,想知道 NUMTODSINTERVAL 是否适用于时间戳间隔?
    • @San - timestamp arithmetic 的结果无论如何都是interval,所以你不需要将它转换为一个。
    • 如果您从TIMESTAMP 中减去TIMESTAMP 或从DATE 中减去TIMESTAMP,Oracle 将为您提供INTERVAL DAY TO SECOND 结果。你不需要转换。仅当从 DATE 中减去 DATE 时才需要。
    • 感谢 Ed 和 Alex 的解释。Alex 我的问题是 end_date 和 start_date 是否都有 TIMESTAMP 数据类型。抱歉,我忘了在上次评论中提到这一点......谢谢
    【解决方案3】:

    要在几秒钟内获得差异,您可以使用它

    select round(24 * 60 * 60* (TO_DATE('2017/02/17 9:32:25', 'YYYY/MM/DD HH:MI:SS') - TO_DATE('2017/02/17 8:30:30', 'YYYY/MM/DD HH:MI:SS'))) from dual;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-04-15
      • 2023-04-01
      • 1970-01-01
      • 2018-07-25
      • 1970-01-01
      • 2013-12-06
      • 2020-08-15
      相关资源
      最近更新 更多