如何计算Oracle中两个时间戳之间的时差(以毫秒为单位)?
答案 0 :(得分:69)
当你减去两个TIMESTAMP
类型的变量时,你得到一个INTERVAL DAY TO SECOND
,它包括一些毫秒和/或微秒,具体取决于平台。如果数据库在Windows上运行,systimestamp
通常会有几毫秒。如果数据库在Unix上运行,systimestamp
通常会有几微秒。
1 select systimestamp - to_timestamp( '2012-07-23', 'yyyy-mm-dd' )
2* from dual
SQL> /
SYSTIMESTAMP-TO_TIMESTAMP('2012-07-23','YYYY-MM-DD')
---------------------------------------------------------------------------
+000000000 14:51:04.339000000
您可以使用EXTRACT
功能提取INTERVAL DAY TO SECOND
SQL> ed
Wrote file afiedt.buf
1 select extract( day from diff ) days,
2 extract( hour from diff ) hours,
3 extract( minute from diff ) minutes,
4 extract( second from diff ) seconds
5 from (select systimestamp - to_timestamp( '2012-07-23', 'yyyy-mm-dd' ) diff
6* from dual)
SQL> /
DAYS HOURS MINUTES SECONDS
---------- ---------- ---------- ----------
0 14 55 37.936
然后,您可以将每个组件转换为毫秒并添加它们
SQL> ed
Wrote file afiedt.buf
1 select extract( day from diff )*24*60*60*1000 +
2 extract( hour from diff )*60*60*1000 +
3 extract( minute from diff )*60*1000 +
4 round(extract( second from diff )*1000) total_milliseconds
5 from (select systimestamp - to_timestamp( '2012-07-23', 'yyyy-mm-dd' ) diff
6* from dual)
SQL> /
TOTAL_MILLISECONDS
------------------
53831842
然而,通常情况下,拥有INTERVAL DAY TO SECOND
表示或具有小时,分钟,秒等的单独列更有用,而不是计算两个TIMESTAMP
之间的总毫秒数。值。
答案 1 :(得分:21)
这是一个存储过程来执行此操作:
CREATE OR REPLACE function timestamp_diff(a timestamp, b timestamp) return number is
begin
return extract (day from (a-b))*24*60*60 +
extract (hour from (a-b))*60*60+
extract (minute from (a-b))*60+
extract (second from (a-b));
end;
/
Up Vote如果你还想打败那些否定他的工作的Oracle开发人员!
因为第一次比较时间戳应该花大约一个小时左右...
答案 2 :(得分:14)
SELECT numtodsinterval(date1-date2,'day') time_difference from dates;
SELECT (extract(DAY FROM time2-time1)*24*60*60)+
(extract(HOUR FROM time2-time1)*60*60)+
(extract(MINUTE FROM time2-time1)*60)+
extract(SECOND FROM time2-time1)
into diff FROM dual;
RETURN diff;
答案 3 :(得分:3)
Select date1 - (date2 - 1) * 24 * 60 *60 * 1000 from Table;
答案 4 :(得分:2)
我知道此问题已得到详尽解答,但我想与所有人分享我的功能。它使您可以选择以天,小时,分钟,秒或毫秒为单位来选择答案。您可以对其进行修改以适合您的需求。
CREATE OR REPLACE FUNCTION Return_Elapsed_Time (start_ IN TIMESTAMP, end_ IN TIMESTAMP DEFAULT SYSTIMESTAMP, syntax_ IN NUMBER DEFAULT NULL) RETURN VARCHAR2 IS
FUNCTION Core (start_ IN TIMESTAMP, end_ IN TIMESTAMP DEFAULT SYSTIMESTAMP, syntax_ IN NUMBER DEFAULT NULL) RETURN VARCHAR2 IS
day_ VARCHAR2(7); /* This means this FUNCTION only supports up to 99 days */
hour_ VARCHAR2(9); /* This means this FUNCTION only supports up to 999 hours, which is over 41 days */
minute_ VARCHAR2(12); /* This means this FUNCTION only supports up to 9999 minutes, which is over 17 days */
second_ VARCHAR2(18); /* This means this FUNCTION only supports up to 999999 seconds, which is over 11 days */
msecond_ VARCHAR2(22); /* This means this FUNCTION only supports up to 999999999 milliseconds, which is over 11 days */
d1_ NUMBER;
h1_ NUMBER;
m1_ NUMBER;
s1_ NUMBER;
ms_ NUMBER;
/* If you choose 1, you only get seconds. If you choose 2, you get minutes and seconds etc. */
precision_ NUMBER; /* 0 => milliseconds; 1 => seconds; 2 => minutes; 3 => hours; 4 => days */
format_ VARCHAR2(2) := ', ';
return_ VARCHAR2(50);
BEGIN
IF (syntax_ IS NULL) THEN
precision_ := 0;
ELSE
IF (syntax_ = 0) THEN
precision_ := 0;
ELSIF (syntax_ = 1) THEN
precision_ := 1;
ELSIF (syntax_ = 2) THEN
precision_ := 2;
ELSIF (syntax_ = 3) THEN
precision_ := 3;
ELSIF (syntax_ = 4) THEN
precision_ := 4;
ELSE
precision_ := 0;
END IF;
END IF;
SELECT EXTRACT(DAY FROM (end_ - start_)) INTO d1_ FROM DUAL;
SELECT EXTRACT(HOUR FROM (end_ - start_)) INTO h1_ FROM DUAL;
SELECT EXTRACT(MINUTE FROM (end_ - start_)) INTO m1_ FROM DUAL;
SELECT EXTRACT(SECOND FROM (end_ - start_)) INTO s1_ FROM DUAL;
IF (precision_ = 4) THEN
IF (d1_ = 1) THEN
day_ := ' day';
ELSE
day_ := ' days';
END IF;
IF (h1_ = 1) THEN
hour_ := ' hour';
ELSE
hour_ := ' hours';
END IF;
IF (m1_ = 1) THEN
minute_ := ' minute';
ELSE
minute_ := ' minutes';
END IF;
IF (s1_ = 1) THEN
second_ := ' second';
ELSE
second_ := ' seconds';
END IF;
return_ := d1_ || day_ || format_ || h1_ || hour_ || format_ || m1_ || minute_ || format_ || s1_ || second_;
RETURN return_;
ELSIF (precision_ = 3) THEN
h1_ := (d1_ * 24) + h1_;
IF (h1_ = 1) THEN
hour_ := ' hour';
ELSE
hour_ := ' hours';
END IF;
IF (m1_ = 1) THEN
minute_ := ' minute';
ELSE
minute_ := ' minutes';
END IF;
IF (s1_ = 1) THEN
second_ := ' second';
ELSE
second_ := ' seconds';
END IF;
return_ := h1_ || hour_ || format_ || m1_ || minute_ || format_ || s1_ || second_;
RETURN return_;
ELSIF (precision_ = 2) THEN
m1_ := (((d1_ * 24) + h1_) * 60) + m1_;
IF (m1_ = 1) THEN
minute_ := ' minute';
ELSE
minute_ := ' minutes';
END IF;
IF (s1_ = 1) THEN
second_ := ' second';
ELSE
second_ := ' seconds';
END IF;
return_ := m1_ || minute_ || format_ || s1_ || second_;
RETURN return_;
ELSIF (precision_ = 1) THEN
s1_ := (((((d1_ * 24) + h1_) * 60) + m1_) * 60) + s1_;
IF (s1_ = 1) THEN
second_ := ' second';
ELSE
second_ := ' seconds';
END IF;
return_ := s1_ || second_;
RETURN return_;
ELSE
ms_ := ((((((d1_ * 24) + h1_) * 60) + m1_) * 60) + s1_) * 1000;
IF (ms_ = 1) THEN
msecond_ := ' millisecond';
ELSE
msecond_ := ' milliseconds';
END IF;
return_ := ms_ || msecond_;
RETURN return_;
END IF;
END Core;
BEGIN
RETURN(Core(start_, end_, syntax_));
END Return_Elapsed_Time;
例如,如果我现在使用Return_Elapsed_Time(TO_TIMESTAMP('12 .04.2017 12:00:00.00','DD.MM.YYYY HH24:MI:SS)立即(12.10.2018 11:17:00.00)调用此函数.FF'),SYSTIMESTAMP),则应返回以下内容:
47344620000 milliseconds
答案 5 :(得分:1)
最好使用这样的程序:
CREATE OR REPLACE FUNCTION timestamp_diff
(
start_time_in TIMESTAMP
, end_time_in TIMESTAMP
)
RETURN NUMBER
AS
l_days NUMBER;
l_hours NUMBER;
l_minutes NUMBER;
l_seconds NUMBER;
l_milliseconds NUMBER;
BEGIN
SELECT extract(DAY FROM end_time_in-start_time_in)
, extract(HOUR FROM end_time_in-start_time_in)
, extract(MINUTE FROM end_time_in-start_time_in)
, extract(SECOND FROM end_time_in-start_time_in)
INTO l_days, l_hours, l_minutes, l_seconds
FROM dual;
l_milliseconds := l_seconds*1000 + l_minutes*60*1000 + l_hours*60*60*1000 + l_days*24*60*60*1000;
RETURN l_milliseconds;
END;
您可以致电:
进行检查SELECT timestamp_diff (TO_TIMESTAMP('12.04.2017 12:00:00.00', 'DD.MM.YYYY HH24:MI:SS.FF'),
TO_TIMESTAMP('12.04.2017 12:00:01.111', 'DD.MM.YYYY HH24:MI:SS.FF'))
as milliseconds
FROM DUAL;
答案 6 :(得分:1)
我知道很多人发现此解决方案简单明了:
create table diff_timestamp (
f1 timestamp
, f2 timestamp);
insert into diff_timestamp values(systimestamp-1, systimestamp+2);
commit;
select cast(f2 as date) - cast(f1 as date) from diff_timestamp;
宾果!
答案 7 :(得分:0)
在格式之间正确投放的时间戳,否则字段可能会被误解。
当从表TableXYZ中考虑两个不同的日期(Date2,Date1)时,这是一个正确的工作示例。
SELECT ROUND (totalSeconds / (24 * 60 * 60), 1) TotalTimeSpendIn_DAYS,
ROUND (totalSeconds / (60 * 60), 0) TotalTimeSpendIn_HOURS,
ROUND (totalSeconds / 60) TotalTimeSpendIn_MINUTES,
ROUND (totalSeconds) TotalTimeSpendIn_SECONDS
FROM (SELECT ROUND (
EXTRACT (DAY FROM timeDiff) * 24 * 60 * 60
+ EXTRACT (HOUR FROM timeDiff) * 60 * 60
+ EXTRACT (MINUTE FROM timeDiff) * 60
+ EXTRACT (SECOND FROM timeDiff))
totalSeconds,
FROM (SELECT TO_TIMESTAMP (
TO_CHAR (Date2,
'yyyy-mm-dd HH24:mi:ss')
- 'yyyy-mm-dd HH24:mi:ss'),
TO_TIMESTAMP (
TO_CHAR (Date1,
'yyyy-mm-dd HH24:mi:ss'),
'yyyy-mm-dd HH24:mi:ss')
timeDiff
FROM TableXYZ))
答案 8 :(得分:0)
上面有一些语法错误,请在oracle上使用以下内容:
SELECT ROUND (totalSeconds / (24 * 60 * 60), 1) TotalTimeSpendIn_DAYS,
ROUND (totalSeconds / (60 * 60), 0) TotalTimeSpendIn_HOURS,
ROUND (totalSeconds / 60) TotalTimeSpendIn_MINUTES,
ROUND (totalSeconds) TotalTimeSpendIn_SECONDS
FROM
(SELECT ROUND ( EXTRACT (DAY FROM timeDiff) * 24 * 60 * 60 + EXTRACT (HOUR FROM timeDiff) * 60 * 60 + EXTRACT (MINUTE FROM timeDiff) * 60 + EXTRACT (SECOND FROM timeDiff)) totalSeconds
FROM
(SELECT TO_TIMESTAMP(TO_CHAR( date2 , 'yyyy-mm-dd HH24:mi:ss'), 'yyyy-mm-dd HH24:mi:ss') - TO_TIMESTAMP(TO_CHAR(date1, 'yyyy-mm-dd HH24:mi:ss'),'yyyy-mm-dd HH24:mi:ss') timeDiff
FROM TABLENAME
)
);
答案 9 :(得分:0)
I)如果您需要计算两个时间戳列之间的经过时间(以秒为单位),请尝试以下操作:
SELECT
extract ( day from (end_timestamp - start_timestamp) )*86400
+ extract ( hour from (end_timestamp - start_timestamp) )*3600
+ extract ( minute from (end_timestamp - start_timestamp) )*60
+ extract ( second from (end_timestamp - start_timestamp) )
FROM table_name
II)如果你想在字符格式中显示时差,试试这个:
SELECT to_char (end_timestamp - start_timestamp) FROM table_name
答案 10 :(得分:0)
我已经发布了here一些将时间间隔转换为纳秒和将纳秒转换为间隔的方法。这些方法具有纳秒级的精度。
您只需将其调整为毫秒而不是纳秒。
一种将间隔转换为纳秒的较短方法。
SELECT (EXTRACT(DAY FROM (
INTERVAL '+18500 09:33:47.263027' DAY(5) TO SECOND --Replace line with desired interval --Maximum value: INTERVAL '+694444 10:39:59.999999999' DAY(6) TO SECOND(9) or up to 3871 year
) * 24 * 60) * 60 + EXTRACT(SECOND FROM (
INTERVAL '+18500 09:33:47.263027' DAY(5) TO SECOND --Replace line with desired interval
))) * 100 AS MILLIS FROM DUAL;
MILLIS
1598434427263.027