Oracle SQL时差,单位为HH:MM:SS
我正在尝试获取Oracle数据库中的时差。除一行外,所有行的时差都可以。这是一个问题Oracle SQL时差,单位为HH:MM:SS,sql,oracle,date,timestamp,Sql,Oracle,Date,Timestamp,我正在尝试获取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 时间差出现
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
时间差出现在以下行中:
通话结束:“2020-02-20 13:00:20”
请拨打电话开始:“2020-02-20 12:56:03”
返回的结果是“11:55:43”,这是错误的。由于正确答案应为“00:04:17”我不确定您是否希望结果作为间隔或时间戳,但这应该满足您的要求:
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
是一个数据库文件。假设您的数据类型是字符串,您确实应该将它们存储为日期数据类型,您可以使用: 选择SUBSTR 马克斯 截止日期呼叫结束,“YYYY-MM-DD HH24:MI:SS” -截止日期呼叫开始,“YYYY-MM-DD HH24:MI:SS” 第1天到第2天 , 4. 8. 随时待命 来自电话 如果它们已经是日期数据类型,则在MAX聚合中,只需使用: 通话结束-通话开始第1天至第2天 因此,对于您的数据: 创建表调用call_end,call_start AS 从双屏幕中选择“2020-02-20 13:00:20”、“2020-02-20 12:56:03” 这将产生:
Gyl先生,你也可以这样做:这个解决方案也会考虑到通话时间在几天内通过增加这些时间在一起:
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
因此,您可以实现为
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
看起来您的表已经将调用开始/结束时间存储为日期,您正在执行从日期到字符串的隐式转换,然后再转换回日期。如果在NLS\u日期\u格式设置中使用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')
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
但你的regex却不这么认为
因为它们是日期,所以完全跳过转换的这一部分,如果您希望间隔从以下位置开始工作,则直接转换为时间戳:
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小时的电话来说,这将无法正常工作。过去,调制解调器电话经常出现这种情况,但这种情况仍然可能发生;但你的间歇也不会接近。两者都忽略任何完整的天数,只显示剩余的天数。当然,有很多方法可以解决这个问题,但你需要决定如何显示它——像interval那样使用单独的天数计数,或者允许“小时”数超过24小时。。。但是你可能会超过99小时
您的问题显示通话结束时间为2020-02-20 13:00:20,这表明您的客户在查询表格时就是这样显示的。我认为有些客户机是PL/SQL开发人员,但不确定,已经有一段时间了,他们使用自己的首选项/设置,而不是遵守会话的NLS设置。但当Oracle必须进行隐式转换时,这对其内部行为没有影响。请参见下面的响应,但这只会在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 ;
我认为是另外一行导致了这个问题,您可以删除MAX并尝试运行查询,看看它是否获取了两行。为什么您认为是这一行导致了这个问题?是否有一个唯一的键可以过滤以确保只获取该行及其结果?另外,为什么要将通话开始/结束时间存储为字符串?如果您是-可能它们已经是日期,并且您正在进行隐式转换-您的NLS日期/时间戳格式设置是什么,您的客户端是否覆盖了它们?
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
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
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 ;