如果它们是 TIMESTAMP,那么您可以使用 TIMESTAMP 算术导致 INTERVAL DAY TO SECOND 数据类型这一事实。给定超过 2 天的时间,TRUNC(<end_date>) 将提供中间日期的午夜日期。
SQL> with the_data as (
2 select to_timestamp('2014-05-01 23:56:00','yyyy-mm-dd hh24:mi:ss') as s
3 , to_timestamp('2014-05-02 01:04:00','yyyy-mm-dd hh24:mi:ss') as e
4 from dual
5 union
6 select to_timestamp('2014-05-01 23:56:00','yyyy-mm-dd hh24:mi:ss') as s
7 , to_timestamp('2014-05-01 23:57:00','yyyy-mm-dd hh24:mi:ss') as e
8 from dual
9 )
10 select case when trunc(e) = trunc(s) then e - s
11 else trunc(e) - s
12 end as day1
13 , case when trunc(e) = trunc(s) then null
14 else e - trunc(e)
15 end as day2
16 from the_data;
DAY1 DAY2
------------------------------ ------------------------------
+000000000 00:01:00.000000000
+000000000 00:04:00.000000000 +000000000 01:04:00.000000000
您需要 CASE 语句,因为您需要做不同的事情,具体取决于您的时间戳是否在同一天。如果您的数据类型实际上是 DATE,那么您最终会以天数作为返回的数据类型
SQL> with the_data as (
2 select to_date('2014-05-01 23:56:00','yyyy-mm-dd hh24:mi:ss') as s
3 , to_date('2014-05-02 01:04:00','yyyy-mm-dd hh24:mi:ss') as e
4 from dual
5 union
6 select to_date('2014-05-01 23:56:00','yyyy-mm-dd hh24:mi:ss') as s
7 , to_date('2014-05-01 23:57:00','yyyy-mm-dd hh24:mi:ss') as e
8 from dual
9 )
10 select case when trunc(e) = trunc(s) then e - s
11 else trunc(e) - s
12 end as day1
13 , case when trunc(e) = trunc(s) then null
14 else e - trunc(e)
15 end as day2
16 from the_data;
DAY1 DAY2
---------- ----------
0.00069444
0.00277777 0.04444444
然后,您可以将此分数添加到当前 SYSTIMESTAMP 中,然后再将其删除,从而将其转换为小时数和分钟数。
select systimestamp + case when trunc(e) = trunc(s) then e - s
else trunc(e) - s
end
- systimestamp as day1
, systimestamp + case when trunc(e) = trunc(s) then null
else e - trunc(e)
end
- systimestamp
from the_data;
之所以有效,是因为您正在创建超过当前时间戳的正确分钟数,然后再次将其删除。但是,由于 TIMESTAMP 算法会产生 INTERVAL DAY TO SECOND,因此您已将其转换为正确的格式。
最好以最适合的数据类型存储数据。如果你想format this differently,你可以在从数据库中提取时这样做。