如何在oracle中减去2个日期以获得小时和分钟的结果

时间:2011-09-18 08:09:34

标签: sql oracle date-arithmetic

我想减去2个日期,并用小时数表示小时和分钟的结果。

我有下表,我这样做,但结果并不理想。

有一些细微的变化,我确信这是简单的算术,但我没有把它弄好。

select start_time, end_time, (end_time-start_time)*24 from 
come_leav;    

START_TIME          END_TIME            (END_TIME-START_TIME)*24    
------------------- ------------------- ------------------------      
21-06-2011 14:00:00 21-06-2011 16:55:00  2.9166667      
21-06-2011 07:00:00 21-06-2011 16:50:00  9.8333333      
21-06-2011 07:20:00 21-06-2011 16:30:00  9.1666667      

我想要结果(end_time-start_time)如下所示。

16:55- 14:00 = 2.55      
16:50-07:00 = 9.5      
16:30-7:20 = 9.1 and so on.    

我该怎么做?

8 个答案:

答案 0 :(得分:4)

SQL> edit
Wrote file afiedt.buf

  1  select start_date
  2      , end_date
  3      , (24 * extract(day from (end_date - start_date) day(9) to second))
  4          + extract(hour from (end_date - start_date) day(9) to second)
  5          + ((1/100) * extract(minute from (end_date - start_date) day(9) to second)) as "HOUR.MINUTE"
  6* from t
SQL> /

START_DATE          END_DATE            HOUR.MINUTE
------------------- ------------------- -----------
21-06-2011 14:00:00 21-06-2011 16:55:00        2.55
21-06-2011 07:00:00 21-06-2011 16:50:00         9.5
21-06-2011 07:20:00 21-06-2011 16:30:00         9.1

对于那些遇到此代码的人应该注意,小数部分是实际的微小差异,而不是一小时的一部分。因此,.5代表50 minutes,而非30 minutes

答案 1 :(得分:2)

试试这个

round(to_number(end_time - start_time) * 24)

答案 2 :(得分:2)

Oracle将日期表示为天数,因此(end_time-start_time)*24会为您提供小时数。假设您在2.9166667列中有这个数字(例如h)。然后,您可以轻松地将其转换为您想要的格式:FLOOR(h) + (h-FLOOR(h))/100*60

示例:

WITH diff AS (
    SELECT (TO_DATE('21-06-2011 16:55:00', 'DD-MM-YYYY HH24:MI:SS') - TO_DATE('21-06-2011 14:00:00', 'DD-MM-YYYY HH24:MI:SS'))*24 h
    FROM dual
) SELECT FLOOR(h) + (h-FLOOR(h))/100*60
FROM diff

在你的情况下:

SELECT start_time, end_time,
    FLOOR((end_time-start_time)*24) + ((end_time-start_time)*24-FLOOR((end_time-start_time)*24))/100*60 AS hours_diff
FROM come_leav 

答案 3 :(得分:0)

试试这个:

    SELECT
    TRIM(TO_CHAR(TRUNC(((86400*(end_time - start_time))/60)/60)-24*(trunc((((86400*(end_time - start_time))/60)/60)/24)),'00')) ||'.'||
    TRIM(TO_CHAR(TRUNC((86400*(end_time - start_time))/60)-60*(trunc(((86400*(end_time - start_time))/60)/60)),'00')) ||'.'  as duration
FROM come_leav;

答案 4 :(得分:0)

编辑:如果您需要一个号码,那么

    trunc(end_date-start_date)*24+
    to_number(to_char(trunc(sysdate)+(end_date-start_date),'HH24.MI'))

对于字符串结果,如果delta小于24H: 我会选择

    to_char(trunc(sysdate)+(end_date-start_date),'HH24.MI')

...'HH24:MI:SS',但这是我个人的偏好。

如果超过24小时,我会以

为前缀
    trunc(end_date-start_date)||"days "||
    to_char(trunc(sysdate)+(end_date-start_date),'HH24.MI')

是的,因为oracle在几天内计算,精确到秒,你正在处理算术问题。一次,因为你只处理分钟(所以你可能将你的数字四舍五入到trunc(days*24*60+0.5)/24/60),但是对于数字1/24/60的二进制运算不精确可能仍然会给你带来麻烦。

Edit2.1:

    to_char(24*(trunc(end_date)-trunc(start_date))+to_number(to_char(end_date,'HH24.MI'))-to_number(to_char(start_date,'HH24.MI')),'99999.99')

但结果可能会让平均水平相当混乱,因为小数7.50表示7个半小时,或者至少7小时50分钟,与7小时10分钟的经过时间相反。

答案 5 :(得分:0)

此查询对我非常有用,如果任何正文需要start_date和end_date之间的差异,如HH:MI:SS请使用此查询。

SELECT
    TRIM(TO_CHAR(TRUNC(((86400*(end_date - start_date))/60)/60)-24*(trunc((((86400(end_date - start_date))/60)/60)/24)),'00')) ||'.'||
    TRIM(TO_CHAR(TRUNC((86400*(actual_completion_date - actual_start_date))/60)-60*(trunc(((86400*(end_date - start_date))/60)/60)),'00')) ||'.'||
    TRIM(TO_CHAR(TRUNC((86400*(end_date - start_date)))-60*(trunc((86400*(end_date - actual_start_date))/60)),'00')) as duration  
FROM fnd_concurrent_requests; 

答案 6 :(得分:0)

这是一种非常丑陋的方式,第一部分并没有完全由OP提出质疑,但它提供了一种通过减去2个日期字段来获得结果的方法 - 在我的例子中,{{1}今天由CREATED_DATE代表:

SYSDATE

它将输出提供x年,x个月,x天,x小时,x分钟。可以通过更改连接的字符串重新格式化它。

为了更直接地回答这个问题,我已经开始并写出如何将总小时数作为SELECT FLOOR(ABS(MONTHS_BETWEEN(CREATED_DATE, SYSDATE)) / 12) || ' years, ' || (FLOOR(ABS(MONTHS_BETWEEN(CREATED_DATE, SYSDATE))) - (FLOOR(ABS(MONTHS_BETWEEN(CREATED_DATE, SYSDATE)) / 12)) * 12) || ' months, ' -- we take total days - years(as days) - months(as days) to get remaining days || FLOOR((SYSDATE - CREATED_DATE) - -- total days (FLOOR((SYSDATE - CREATED_DATE)/365)*12)*(365/12) - -- years, as days -- this is total months - years (as months), to get number of months, -- then multiplied by 30.416667 to get months as days (and remove it from total days) FLOOR(FLOOR(((SYSDATE - CREATED_DATE)/365)*12 - (FLOOR((SYSDATE - CREATED_DATE)/365)*12)) * (365/12))) || ' days, ' -- Here, we can just get the remainder decimal from total days minus -- floored total days and multiply by 24 || FLOOR( ((SYSDATE - CREATED_DATE)-(FLOOR(SYSDATE - CREATED_DATE)))*24 ) || ' hours, ' -- Minutes just use the unfloored hours equation minus floored hours, -- then multiply by 60 || ROUND( ( ( ((SYSDATE - CREATED_DATE)-(FLOOR(SYSDATE - CREATED_DATE)))*24 ) - FLOOR((((SYSDATE - CREATED_DATE)-(FLOOR(SYSDATE - CREATED_DATE)))*24)) )*60 ) || ' minutes' AS AGE FROM MyTable` 分钟:

hours.minutes

答案 7 :(得分:-2)

你可以使用摘录:

SELECT start_time, end_time, extract(HOUR FROM end_time-start_time) || '.' || extract(MINUTE FROM end_time-start_time)  
From come_leav;