==============================实践后===============================
如果两个字段都是DATE型,那么直接用END_DATE - BEGIN_DATE即可,不需要任何转型,取整直接用TRUNC即可:TRUNC(END_DATE - BEGIN_DATE),这样是直接将小数部分舍去。
=====================================================================
*************实例(包括MONTHS_BETWEEN,ADD_MONTHS,MOD,LAST_DAY的用法)******************
/*
解决方案;本例假设用户统计2007-05月份的报告及时率
1.需要要取得2007-05月份需要做随访的婴儿信息
2.再查询出这些婴儿中在本次随访中已经做了随访并且满足<=20天的
*/
/*2007-5月需要随访的婴儿ID*/
select T.ID,T.* /*不太准确*/
from fy_new_baby t
where
mod(trunc(months_between(TO_DATE('2007-05-31', 'yyyy-mm-dd') ,t.birthday)),12) in (1,3,6,9,12)
and t.live = '1'
select T.ID,T.* /*比较准确*/
FROM FY_NEW_BABY T
WHERE MOD(TRUNC(MONTHS_BETWEEN(TO_DATE('2007-05-31','yyyy-mm-dd'),T.BIRTHDAY)),12) IN (1,3,6,9,12)
AND T.LIVE = '1'
/*本月需要做随访的并且已经做了随访的记录
(其中也包括了以前做过随访而并非算是本次随访的,后面通过(随访日期-本次应该随访日期)>0来将其排除掉*/
select v.* from fy_register_visit v
where v.new_baby_id in (select T.ID
from fy_new_baby t
where
mod(trunc(months_between(TO_DATE('2007-05-31', 'yyyy-mm-dd') ,t.birthday)),12) in (1,3,6,9,12)
and t.live = '1')
/*出生日期和本月的月差*/
SELECT MONTHS_BETWEEN(TO_DATE('2007-05-31','YYYY-MM-DD'),T.BIRTHDAY) FROM FY_NEW_BABY T
/*本月需要做随访的婴儿在本月应该随访的日期*/
select T.ID,T.BIRTHDAY,ADD_MONTHS(T.BIRTHDAY,TRUNC(MONTHS_BETWEEN(TO_DATE('2007-05-31','YYYY-MM-DD'),T.BIRTHDAY)) ),t.*
from fy_new_baby t WHERE T.ID IN (select T.ID
from fy_new_baby t
where
mod(trunc(months_between(TO_DATE('2007-05-31', 'yyyy-mm-dd') ,t.birthday)),12) in (1,3,6,9,12)
and t.live = '1')
/*需要在本月做随访的婴儿的随访日期-本月应该做随访的日期*/
select ff.id,v.vst_date,ff.birthday, ff.shouldvisit,(v.vst_date-ff.shouldvisit) as day from fy_register_visit v,
( select T.ID as id,T.BIRTHDAY as birthday,ADD_MONTHS(T.BIRTHDAY,TRUNC(MONTHS_BETWEEN(TO_DATE('2007-05-31','YYYY-MM-DD'),T.BIRTHDAY)) ) as shouldvisit
from fy_new_baby t WHERE T.ID IN (select T.ID
from fy_new_baby t
where
mod(trunc(months_between(TO_DATE('2007-05-31', 'yyyy-mm-dd') ,t.birthday)),12) in (1,3,6,9,12)
and t.live = '1') ) ff
where v.new_baby_id = ff.id
/*随访表中满足(随访日期-本月应该随访日期<=20)的*/
select ff.id,v.vst_date,v.vst_zonecode,ff.birthday, ff.shouldvisit,(v.vst_date-ff.shouldvisit) as day from fy_register_visit v,
( select T.ID as id,T.BIRTHDAY as birthday,ADD_MONTHS(T.BIRTHDAY,TRUNC(MONTHS_BETWEEN(TO_DATE('2007-05-31','YYYY-MM-DD'),T.BIRTHDAY)) ) as shouldvisit
from fy_new_baby t WHERE T.ID IN (select T.ID
from fy_new_baby t
where
mod(trunc(months_between(TO_DATE('2007-05-31', 'yyyy-mm-dd') ,t.birthday)),12) in (1,3,6,9,12)
and t.live = '1') ) ff
where v.new_baby_id = ff.id
and v.vst_date-ff.shouldvisit<=20
and v.vst_date-ff.shouldvisit>=0
/*2007-05月份需要随访的活产婴儿总数---按地区分组
因为FY_NEW_BABY表中没有地区字段,所以需要关联FY_PREGNANT_REG表*/
select B.REP_ZONECODE , count(*) as shouldVisitNum
FROM FY_NEW_BABY T,FY_PREGNANT_REG B
WHERE MOD(TRUNC(MONTHS_BETWEEN(TO_DATE('2007-05-31','yyyy-mm-dd'),T.BIRTHDAY)),12) IN (1,3,6,9,12)
AND T.LIVE = '1'
AND T.CARD_ID = B.ID
GROUP BY B.REP_ZONECODE
/*2007-05月份需要随访的婴儿并且已经存在在随访表中并满足(0=<随访日期-本月应该随访日期<=20)的*/
select v.vst_zonecode, count(distinct v.id) as visitNum /*ff.id,v.vst_date,ff.birthday, ff.shouldvisit,(v.vst_date-ff.shouldvisit) as day*/
from fy_register_visit v,
(select T.ID as id,
T.BIRTHDAY as birthday,
ADD_MONTHS(T.BIRTHDAY,
TRUNC(MONTHS_BETWEEN(TO_DATE('2007-05-31',
'YYYY-MM-DD'),
T.BIRTHDAY))) as shouldvisit
from fy_new_baby t
WHERE T.ID IN (select T.ID
from fy_new_baby t
where mod(trunc(months_between(TO_DATE('2007-05-31',
'yyyy-mm-dd'),
t.birthday)),
12) in (1, 3, 6, 9, 12)
and t.live = '1')) ff
where v.new_baby_id = ff.id
and v.vst_date - ff.shouldvisit <= 20
and v.vst_date - ff.shouldvisit >= 0
group by v.vst_zonecode
***************************************用例END****************************************
===========================参考资料================================================
Oracle中如何计算时间差
计算时间差是Oracle DATA数据类型的一个常见问题。Oracle支持日期计算,你可以创建诸如“日期1-日期2”这样的表达式来计算这两个日期之间的时间差。
一旦你发现了时间差异,你可以使用简单的技巧来以天、小时、分钟或者秒为单位来计算时间差。为了得到数据差,你必须选择合适的时间度量单位,这样就可以进行数据格式隐藏。
使用完善复杂的转换函数来转换日期是一个诱惑,但是你会发现这不是最好的解决方法。
round(to_number(end-date-start_date))- 消逝的时间(以天为单位)
round(to_number(end-date-start_date)*24)- 消逝的时间(以小时为单位)
round(to_number(end-date-start_date)*1440)- 消逝的时间(以分钟为单位)
显示时间差的默认模式是什么?为了找到这个问题的答案,让我们进行一个简单的SQL *Plus查询。
SQL> select sysdate-(sysdate-3) from dual;
SYSDATE-(SYSDATE-3)
-------------------
3
这里,我们看到了Oracle使用天来作为消逝时间的单位,所以我们可以很容易的使用转换函数来把它转换成小时或者分钟。然而,当分钟数不是一个整数时,我们就会遇到放置小数点的问题。
Select
(sysdate-(sysdate-3.111))*1440
from
dual;
(SYSDATE-(SYSDATE-3.111))*1440
------------------------------
4479.83333
当然,我们可以用ROUND函数(即取整函数)来解决这个问题,但是要记住我们必须首先把DATE数据类型转换成NUMBER数据类型。
Select
round(to_number(sysdate-(sysdate-3.111))*1440)
from
dual;
ROUND(TO_NUMBER(SYSDATE-(SYSDATE-3.111))*1440)
----------------------------------------------
4480
我们可以用这些函数把一个消逝时间近似转换成分钟并把这个值写入Oracle表格中。在这个例子里,我们有一个离线(logoff)系统级触发机制来计算已经开始的会话时间并把它放入一个Oracle STATSPACK USER_LOG扩展表格之中。
Update
perfstat.stats$user_log
set
elapsed_minutes =
round(to_number(logoff_time-logon_time)*1440)
where
user = user_id
and
elapsed_minutes is NULL;
posted on 2007-06-05 18:44
阿伟 阅读(344)
评论(0) 编辑 收藏 所属分类:
DateBase