==============================實踐后===============================
如果兩個字段都是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
阿偉 閱讀(346)
評論(0) 編輯 收藏 所屬分類:
DateBase