[英]Oracle SQL time difference in HH:MM:SS
我正在嘗試獲取 Oracle 數據庫中的時差。 除了一行之外,所有行的時間差都可以。 這是查詢
SELECT MAX(REGEXP_SUBSTR (CAST(TO_DATE(call_end, 'YYYY/MM/DD HH24:MI:SS') AS TIMESTAMP) - CAST(TO_DATE(call_start, 'YYYY/MM/DD HH24:MI:SS') AS TIMESTAMP), '\d{2}:\d{2}:\d{2}')) AS call_time
FROM calls
時差發生在以下行:
call_end: '2020-02-20 13:00:20'
call_start: '2020-02-20 12:56:03'
返回的結果是'11:55:43',這是錯誤的。 因為正確答案應該是'00:04:17'
看起來您的表已經將呼叫開始/結束時間存儲為日期,並且您正在進行從日期到字符串的隱式轉換,然后再轉換回日期。 如果在 NLS_DATE_FORMAT 設置中使用 HH 而不是 HH24,則可以看到該結果:
alter session set nls_date_format = 'YYYY-MM-DD HH:MI:SS';
with calls (call_end, call_start) as (
select cast(timestamp '2020-02-20 13:00:20' as date), cast(timestamp '2020-02-20 12:56:03' as date) from dual
)
SELECT MAX(REGEXP_SUBSTR (CAST(TO_DATE(call_end, 'YYYY/MM/DD HH24:MI:SS') AS TIMESTAMP) - CAST(TO_DATE(call_start, 'YYYY/MM/DD HH24:MI:SS') AS TIMESTAMP), '\d{2}:\d{2}:\d{2}')) AS call_time
FROM calls;
CALL_TIME
---------------------------
11:55:43
當你做
TO_DATE(call_end, 'YYYY/MM/DD HH24:MI:SS')
因為這已經是你真正要做的約會了:
TO_DATE(TO_CHAR(call_end, <NLS_DATE_FORMAT>), 'YYYY/MM/DD HH24:MI:SS')
所以我的設置(和你的必須相似,也許用斜線而不是破折號)是:
TO_DATE(TO_CHAR(call_end, 'YYYY-MM-DD HH:MI:SS'), 'YYYY/MM/DD HH24:MI:SS')
並且HH和HH24之間的不匹配變得更加明顯。 因此,您實際上是將字符串 2020-02-20 01:00:20 和 2020-02-20 12:56:03 轉換回日期,以及 01:00:20 和 12:56:03 之間的時差是 11:55:43。 嗯 - 實際上,它是負11 小時:
SELECT CAST(TO_DATE(call_end, 'YYYY/MM/DD HH24:MI:SS') AS TIMESTAMP) - CAST(TO_DATE(call_start, 'YYYY/MM/DD HH24:MI:SS') AS TIMESTAMP)
FROM calls;
CAST(TO_DATE(CALL_E
-------------------
-00 11:55:43.000000
但你的正則表達式沒有接受。
因為它們是日期,所以完全跳過轉換的那部分,如果您希望間隔工作,只需直接轉換為時間戳:
SELECT MAX(REGEXP_SUBSTR (CAST(call_end AS TIMESTAMP) - CAST(call_start AS TIMESTAMP), '\d{2}:\d{2}:\d{2}')) AS call_time
FROM calls;
CALL_TIME
---------------------------
00:04:17
或使用子字符串而不是正則表達式,如@MTO 所示。
您也可以將它們保留為日期,將差異作為一天的一小部分,將其添加回午夜的任何名義日期,然后將結果日期轉換為字符串:
SELECT TO_CHAR(date '2000-01-01' + MAX(call_end - call_start), 'HH24:MI:SS') AS call_time
FROM calls;
CALL_TIM
--------
00:04:17
對於持續時間超過 24 小時的呼叫,這將無法正常工作(過去常常看到調制解調器呼叫,但仍然可能發生); 但你的間隔也不會接近。 兩者都忽略任何一整天,只顯示剩余的天數。 當然有辦法處理這個問題,但是您需要決定如何顯示它 - 使用單獨的天數(就像間隔一樣),或者允許“小時”數超過 24 ......但是那么你可能會超過 99 小時...
您的問題顯示呼叫結束時間為 2020-02-20 13:00:20,這表明您的客戶在查詢表格時顯示它的方式。 一些客戶端(我認為是 PL/SQL Developer,但不確定,已經有一段時間了)使用他們自己的首選項/設置而不是遵守會話的 NLS 設置。 但這對 Oracle 在必須進行隱式轉換時的內部行為沒有影響。
我不確定您是否希望將結果作為間隔或時間戳,但這應該可以滿足您的需求:
select t.*, call_end - call_start,
substr(to_char(call_end - call_start, 'HH24:MI:SS'), 12, 8) as str from (select timestamp '2020-02-20 13:00:20.000' as call_end,
timestamp '2020-02-20 12:56:03.000' as call_start
from dual) t
這是一個 db<>fiddle。
假設您的數據類型是字符串(您確實應該將它們存儲為DATE
數據類型),您可以使用:
SELECT SUBSTR(
MAX(
( TO_DATE( call_end, 'YYYY-MM-DD HH24:MI:SS' )
- TO_DATE( call_start, 'YYYY-MM-DD HH24:MI:SS' )
) DAY(1) TO SECOND
),
4,
8
) AS call_time
FROM calls
如果它們已經是DATE
數據類型,那么在MAX
聚合中,只需使用:
( call_end - call_start ) DAY(1) TO SECOND
所以對於你的數據:
CREATE TABLE calls ( call_end, call_start ) AS
SELECT '2020-02-20 13:00:20', '2020-02-20 12:56:03' FROM DUAL
這輸出:
\n | CALL_TIME |\n | :-------- |\n | 00:04:17 |\n
db<> 在這里擺弄
Gyl 先生,您也可以這樣做: db <> fiddle :此解決方案還將通過將這些小時加在一起來考慮呼叫何時失效:
WITH da AS (
SELECT
NUMTODSINTERVAL(TO_DATE('2020-02-20 13:00:20', 'yyyy-mm-dd hh24:mi:ss') - TO_DATE('2020-02-20 12:56:03', 'yyyy-mm-dd hh24:mi:ss'), 'DAY') AS call_diff
FROM
dual ) SELECT
EXTRACT( DAY FROM call_diff )*24 + EXTRACT( HOUR FROM call_diff )|| ':' || EXTRACT( MINUTE FROM call_diff ) || ':' || EXTRACT( SECOND FROM call_diff ) DIFFERENCE
FROM
da
DIFFERENCE| ----------| 0:4:17 |
所以你可以實現為
WITH da AS (
SELECT
NUMTODSINTERVAL(TO_DATE(call_end, 'yyyy-mm-dd hh24:mi:ss') - TO_DATE(call_start, 'yyyy-mm-dd hh24:mi:ss'), 'DAY') AS call_diff
FROM
calls
) SELECT
EXTRACT( DAY FROM call_diff )*24 + EXTRACT( HOUR FROM call_diff )|| ':' || EXTRACT( MINUTE FROM call_diff ) || ':' || EXTRACT( SECOND FROM call_diff ) TIMESTAMP
FROM
da
請參閱下面的回復,但這只會在 24 小時內起作用並返回“00”
WITH sample_lt AS(
SELECT '2020-02-20 12:56:03' START_TIME, '2020-02-20 13:00:20' END_TIME FROM dual
)
SELECT start_time,
end_time,
TO_CHAR (TRUNC (SYSDATE) + (to_date(end_time, 'yyyy-mm-dd HH24:MI:SS') -
to_date(start_time, 'yyyy-mm-dd HH24:MI:SS')
) , 'hh24:mi:ss' ) duration
FROM sample_lt ;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.