oracle 时间相加减

时间:2022-09-22 15:07:18

ORACLE 时间相加(HH:MM)

1.分钟转成不同格式的时间
数据库里有个字段 存的分钟
① 现在想显示成HH:MM格式 假设为514分钟
SELECT to_char((to_date('00:00','HH24:MI')+514/24/60),'HH24:MI') from dual
输出结果:
 08:34
②如果存的是秒 同理  
 SELECT to_char((to_date('00:00:00','HH24:MI:SS')+514/24/60/60),'HH24:MI:SS') from dual
输出结果:
00:08:34 

至于显示成其他的格式,也就不成问题了
2.时分相加
至于为什么要写这个,是因为oracle里没有两个时间相加的处理,两个to_date相减可以,相加就出错了:
 
数据库里有两个字段 存的都是HH:MM格式的时间
假设一个是本月上午缺勤时间合计: 08:30(8个半小时)
另外一个是本月下午缺勤时间合计: 00:30(半小时)
现在想要总缺勤时间,显示成 HH:MM格式
做法有两种
① 正常的逻辑运算(代码或者PLSQL实现的应该比这个容易的多,仅限于SQL实现):

select  LPAD((substr('08:30',1,2) + substr('00:30',1,2)+(substr('08:30',length('08:30')-1,2)+substr('00:30',length('00:30')-1,2))/60),2,'0') || ':' || LPAD(mod((substr('08:30',length('08:30')-1,2)+substr('00:30',length('00:30')-1,2)),60),2,'0') from  dual 
看起来很复杂,而实际上就是把小时相加,分钟相加,之后把分钟满60的小时进位,取余的显示:
取前两位相加得小时:(是因为不确定数据储存的格式是不是严格的HH:MM,而不能借正则分隔“:”)
 
(substr('08:30',1,2) + substr('00:30',1,2) 
取后两位相加得分钟:
(substr('08:30',length('08:30')-1,2)+substr('00:30',length('00:30')-1,2)) 
把分钟满60的小时进位得显示用的小时:
(substr('08:30',length('08:30')-1,2)+substr('00:30',length('00:30')-1,2))/60 
现在小时算完了,不足两位左补零:
 LPAD((substr('08:30',1,2) + substr('00:30',1,2)+(substr('08:30',length('08:30')-1,2)+substr('00:30',length('00:30')-1,2))/60),2,'0')  
把分钟取余得显示用的分钟:
mod((substr('08:30',length('08:30')-1,2)+substr('00:30',length('00:30')-1,2)),60)
 
现在分钟算完了,不足两位左补零:
LPAD(mod((substr('08:30',length('08:30')-1,2)+substr('00:30',length('00:30')-1,2)),60),2,'0') 
最后连上“:”就变成上述的SQL,得到的时间用HH:MM显示了

输出结果:
09:00

②函数实现:
SELECT to_char(to_date('00:00','HH24:MI') +(((to_date('08:30','HH24:MI') - trunc(to_date('08:30','HH24:MI'))) *24*60  + (to_date('00:30','HH24:MI') - trunc(to_date('00:30','HH24:MI'))) *24*60)/24/60),'HH24:MI') from dual
同样看起来很复杂
首先把HH:MM的换成数值:
to_date('08:30','HH24:MI') - trunc(to_date('08:30','HH24:MI'))    
输出结果:.354166666666666666666666666666666666666(其实是代表了一个时间,是以天为单位的)
现在
*24*60 把数值换成分钟:
(to_date('08:30','HH24:MI') - trunc(to_date('08:30','HH24:MI'))) *24*60 
输出结果:510
也就是把
08:30 变成了510分
(to_date('00:30','HH24:MI') - trunc(to_date('00:30','HH24:MI'))) *24*60 
输出结果:30(时间是.020833333333333333333333333333333333333)这两个
也就是把00:30 变成了30分 
然后把两个分钟相加:
 ((to_date('08:30','HH24:MI') - trunc(to_date('08:30','HH24:MI'))) *24*60  + (to_date('00:30','HH24:MI') - trunc(to_date('00:30','HH24:MI'))) *24*60)
 输出结果:
540
剩下的就是显示处理了,和1里面的做法一致:
 
to_char(to_date('00:00','HH24:MI') +(((to_date('08:30','HH24:MI') - trunc(to_date('08:30','HH24:MI'))) *24*60  + (to_date('00:30','HH24:MI') - trunc(to_date('00:30','HH24:MI'))) *24*60)/24/60),'HH24:MI')
输出结果: 

3. 不论是方法①还是方法②,这里都存在一个问题:如果时间相加之后超出23:59,系统就会报错,目前我用的涉及不到这个 就没写出来,如果有用到的直接再转成DD:HH:MM的格式就行了,也就是把小时数满24的进位取显示用的天  
SELECT to_char(to_date('01 00:00','DD HH24:MI') +(((to_date('23:30','HH24:MI') - trunc(to_date('23:30','HH24:MI'))) *24*60  + (to_date('01:30','HH24:MI') - trunc(to_date('01:30','HH24:MI'))) *24*60)/24/60-1),'DD HH24:MI') from dual 
输出结果:01 01:00(25小时)



oracle 时间相减
select to_char((TO_DATE('1970-01-01', 'yyyy-MM-dd') +
               (to_date('10:10:10', 'HH24:mi:ss') -
               to_date('12:10:10', 'HH24:mi:ss'))), 'HH24:mi:ss')
  from dual;

对当前日期增加50分种
SQL> select sysdate, sysdate+numtodsinterval(50,’minute’) from dual ;


SYSDATE             SYSDATE+NUMTODSINTE
——————- ——————-
2010-10-14 21:39:12 2010-10-14 22:29:12
对当前日期增加45秒
SQL> select sysdate, sysdate+numtodsinterval(45,’second’) from dual ;


SYSDATE             SYSDATE+NUMTODSINTE
——————- ——————-
2010-10-14 21:40:06 2010-10-14 21:40:51
对当前日期增加3天
SQL> select sysdate, sysdate+3 from dual ;


SYSDATE             SYSDATE+3
——————- ——————-
2010-10-14 21:40:46 2010-10-17 21:40:46
对当前日期增加4个月
SQL> select sysdate, add_months(sysdate,4) from dual ;


SYSDATE             ADD_MONTHS(SYSDATE,
——————- ——————-
2010-10-14 21:41:43 2011-02-14 21:41:43

对当前日期增加一个小时:
SQL> select sysdate, sysdate+numtodsinterval(1,’hour’) from dual ;


SYSDATE             SYSDATE+NUMTODSINTE
——————- ——————-
2010-10-14 21:38:19 2010-10-14 22:38:19
对当前日期增加50分种

参考: http://hi.baidu.com/fssyleihen/item/c267b7b428034aa1eaba9396