oracle 日期相減 轉載

 

轉自 http://hi.baidu.com/juanjuan_66/blog/item/cf48554c9331fbe6d62afc6a.htmlhtml

oracle日期相減
2012-02-10 12:18
--MONTHS_BETWEEN(date2,date1) 
給出date2-date1的月份 
SQL> select months_between('19-12月-1999','19-3月-1999') mon_between from dual; 

MON_BETWEEN 
----------- 

SQL>select months_between(to_date('2000.05.20','yyyy.mm.dd'),to_date('2005.05.20','yyyy.dd')) mon_betw from dual; 

MON_BETW 
--------- 
-60 

Oracle計算時間差表達式 

--獲取兩時間的相差豪秒數 
select ceil((To_date('2008-05-02 00:00:00' , 'yyyy-mm-dd hh24-mi-ss') - To_date('2008-04-30 23:59:59' , 'yyyy-mm-dd hh24-mi-ss')) * 24 * 60 * 60 * 1000) 相差豪秒數 FROM DUAL; 
/* 
相差豪秒數 
---------- 
86401000 
1 row selected 
*/ 

--獲取兩時間的相差秒數 
select ceil((To_date('2008-05-02 00:00:00' , 'yyyy-mm-dd hh24-mi-ss') - To_date('2008-04-30 23:59:59' , 'yyyy-mm-dd hh24-mi-ss')) * 24 * 60 * 60) 相差秒數 FROM DUAL; 
/* 
相差秒數 
---------- 
86401 
1 row selected 
*/ 

--獲取兩時間的相差分鐘數 
select ceil(((To_date('2008-05-02 00:00:00' , 'yyyy-mm-dd hh24-mi-ss') - To_date('2008-04-30 23:59:59' , 'yyyy-mm-dd hh24-mi-ss'))) * 24 * 60) 相差分鐘數 FROM DUAL; 
/* 
相差分鐘數 
---------- 
1441 
1 row selected 
*/ 

--獲取兩時間的相差小時數 
select ceil((To_date('2008-05-02 00:00:00' , 'yyyy-mm-dd hh24-mi-ss') - To_date('2008-04-30 23:59:59' , 'yyyy-mm-dd hh24-mi-ss')) * 24) 相差小時數 FROM DUAL; 
/* 
相差小時數 
---------- 
25 
1 row selected 
*/ 

--獲取兩時間的相差天數 
select ceil((To_date('2008-05-02 00:00:00' , 'yyyy-mm-dd hh24-mi-ss') - To_date('2008-04-30 23:59:59' , 'yyyy-mm-dd hh24-mi-ss'))) 相差天數 FROM DUAL; 
/* 
相差天數 
---------- 

1 row selected 
*/ 

---------------------------------------- 
注:天數能夠2個日期直接減,這樣更加方便 
---------------------------------------- 

--獲取兩時間月份差 
select (EXTRACT(year FROM to_date('2009-05-01','yyyy-mm-dd')) - EXTRACT(year FROM to_date('2008-04-30','yyyy-mm-dd'))) * 12 +
EXTRACT(month FROM to_date('2008-05-01','yyyy-mm-dd')) - EXTRACT(month FROM to_date('2008-04-30','yyyy-mm-dd')) months 
from dual; 
/* 
MONTHS 
---------- 
13 
1 row selected 
*/ 

-------------------------------------- 
注:可使用months_between函數,更加方便 
-------------------------------------- 

--獲取兩時間年份差 
select EXTRACT(year FROM to_date('2009-05-01','yyyy-mm-dd')) - EXTRACT(year FROM to_date('2008-04-30','yyyy-mm-dd')) years from dual; 
/* 
YEARS 
---------- 





select sysdate,add_months(sysdate,12) from dual; --加1年 
select sysdate,add_months(sysdate,1) from dual; --加1月 
select sysdate,TO_CHAR(sysdate+7,'yyyy-mm-dd HH24:MI:SS') from dual; --加1星期 
select sysdate,TO_CHAR(sysdate+1,'yyyy-mm-dd HH24:MI:SS') from dual; --加1天 
select sysdate,TO_CHAR(sysdate+1/24,'yyyy-mm-dd HH24:MI:SS') from dual; --加1小時 
select sysdate,TO_CHAR(sysdate+1/24/60,'yyyy-mm-dd HH23:MI:SS') from dual; --加1分鐘 
select sysdate,TO_CHAR(sysdate+1/24/60/60,'yyyy-mm-dd HH23:MI:SS') from dual; --加1秒 

select sysdate+7 from dual; --加7天






將當前日期轉換爲上一個月

SELECT TO_CHAR(ADD_MONTHS(SYSDATE, -1), 'yyyymm') --獲取當前時間的前一個月
FROM DUAL;

select sysdate from dual; /**獲取當前時間到秒**/
select sysdate-3 from dual;/**獲取當前2天**/
select round(sysdate) as 格式成日期 from dual;
select to_date('2008-9-2','yyyy_mm_dd') as 格式成日期 from dual;
SELECT TO_CHAR(ADD_MONTHS(SYSDATE, -1), 'yyyymm') FROM DUAL; /**--獲取當前時間的前一個月,正向後**/
Select last_day(sysdate) from dual;/**本月最受一天**/
/***分別取時間的年、月、日***/
Select to_char(sysdate,'YYYY') from dual;
select to_char(sysdate,'mm') from dual;
select to_char(sysdate,'dd') from dual;



一下是轉載 jenry-雲飛揚:

1。上月末天:
SQL> select to_char(add_months(last_day(sysdate),-1),'yyyy-MM-dd') LastDay from
dual;

LASTDAY
----------
2005-05-31

2。上月今天
SQL> select to_char(add_months(sysdate,-1),'yyyy-MM-dd') PreToday from dual;


PRETODAY
----------
2005-05-21

3.上月首天
SQL> select to_char(add_months(last_day(sysdate)+1,-2),'yyyy-MM-dd') firstDay from dual;

FIRSTDAY
----------
2005-05-01

4.按照每週進行統計
SQL> select to_char(sysdate,'ww') from dual group by to_char(sysdate,'ww');

TO
--
25

5。按照每個月進行統計
SQL> select to_char(sysdate,'mm') from dual group by to_char(sysdate,'mm');

TO
--
06

6。按照每季度進行統計
SQL> select to_char(sysdate,'q') from dual group by to_char(sysdate,'q');

T
-
2

7。按照每一年進行統計
SQL> select to_char(sysdate,'yyyy') from dual group by to_char(sysdate,'yyyy');

TO_C
----
2005

8.要找到某月中全部週五的具體日期 
select to_char(t.d,'YY-MM-DD') from ( 
select trunc(sysdate, 'MM')+rownum-1 as d 
from dba_objects 
where rownum < 32) t 
where to_char(t.d, 'MM') = to_char(sysdate, 'MM') --找出當前月份的週五的日期

and trim(to_char(t.d, 'Day')) = '星期五' 
-------- 
03-05-02 
03-05-09 
03-05-16 
03-05-23 
03-05-30 

若是把where to_char(t.d, 'MM') = to_char(sysdate, 'MM')改爲sysdate-90,即爲查找當前月份的前三個月中的每週五的日期。

9.oracle中時間運算

內容以下: 
一、oracle支持對日期進行運算 
二、日期運算時是以天爲單位進行的 
三、當須要以分秒等更小的單位算值時,按時間進制進行轉換便可 
四、進行時間進制轉換時注意加括號,不然會出問題

SQL> alter session set nls_date_format='yyyy-mm-dd hh:mi:ss';

會話已更改。

SQL> set serverout on 
SQL> declare 
2 DateValue date; 
3 begin 
4 select sysdate into DateValue from dual; 
5 dbms_output.put_line('源時間:'||to_char(DateValue)); 
6 dbms_output.put_line('源時間減1天:'||to_char(DateValue-1)); 
7 dbms_output.put_line('源時間減1天1小時:'||to_char(DateValue-1-1/24)); 
8 dbms_output.put_line('源時間減1天1小時1分:'||to_char(DateValue-1-1/24-1/(24*60))); 
9 dbms_output.put_line('源時間減1天1小時1分1秒:'||to_char(DateValue-1-1/24-1/(24*60)-1/(24*60*60))); 
10 end; 
11 / 
源時間:2003-12-29 11:53:41 
源時間減1天:2003-12-28 11:53:41 
源時間減1天1小時:2003-12-28 10:53:41 
源時間減1天1小時1分:2003-12-28 10:52:41 
源時間減1天1小時1分1秒:2003-12-28 10:52:40

PL/SQL 過程已成功完成。


在Oracle中實現時間相加處理
-- 名稱:Add_Times
-- 功能:返回d1與NewTime相加之後的結果,實現時間的相加
-- 說明:對於NewTime中的日期不予考慮
-- 日期:2004-12-07
-- 版本:1.0
-- 做者:Kevin


create or replace function Add_Times(d1 in date,NewTime in date) return date 
is
hh number;
mm number;
ss number;
hours number;
dResult date; 
begin
-- 下面依次取出時、分、秒
select to_number(to_char(NewTime,'HH24')) into hh from dual;
select to_number(to_char(NewTime,'MI')) into mm from dual;
select to_number(to_char(NewTime,'SS')) into ss from dual;
-- 換算出NewTime中小時總和,在一天的百分幾
hours := (hh + (mm / 60) + (ss / 3600))/ 24;
-- 得出時間相加後的結果
select d1 + hours into dResult from dual;
return(dResult);
end Add_Times;


-- 測試用例
-- select Add_Times(sysdate,to_date('2004-12-06 03:23:00','YYYY-MM-DD HH24:MI:SS')) from dual


在Oracle9i中計算時間差
計算時間差是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) 
------------------- 


這裏,咱們看到了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;

查出任一年月所含的工做日
CREATE OR REPLACE FUNCTION Get_WorkingDays(
ny IN VARCHAR2
) RETURN INTEGER IS
/*------------------------------------------------------------------------------------------
函數名稱:Get_WorkingDays
中文名稱:求某一年月中共有多少工做日
做者姓名: XINGPING
編寫時間: 2004-05-22
輸入參數:NY:所求包含工做日數的年月,格式爲yyyymm,如200405
返 回 值:整型值,包含的工做日數目。
算法描述:
1).列舉出參數給出的年月中的每一天。這裏使用了一個表(ljrq是個人庫中的一張表。這個表能夠是有權訪問的、記錄條數至少爲31的任意一張表或視圖)來構造出某年月的每一天。
2).用這些日期和一個已知星期幾的日期相減(2001-12-30是星期天),所得的差再對7求模。若是所求年月在2001-12-30之前,那麼所得的差既是負數,求模後所得值範圍爲大於-6,小於0,如-1表示星期六,故先將求模的結果加7,再求7的模.
3).過濾掉結果集中值爲0和6的元素,而後求count,所得即爲工做日數目。 
-------------------------------------------------------------------------------------------------*/
Result INTEGER;
BEGIN
SELECT COUNT(*) INTO Result
FROM (SELECT MOD(MOD(q.rq-to_date('2001-12-30','yyyy-mm-dd'),7),7) weekday
FROM ( SELECT to_date(ny||t.dd,'yyyymmdd') rq
FROM (SELECT substr(100+ROWNUM,2,2) dd 
FROM ljrq z WHERE Rownum<=31
) t
WHERE to_date(ny||t.dd,'yyyymmdd') 
BETWEEN to_date(ny,'yyyymm') 
AND last_day(to_date(ny,'yyyymm'))
)q
) a 
WHERE a.weekday NOT IN(0,6); 
RETURN Result; 
END Get_WorkingDays;

______________________________________

還有一個版本
CREATE OR REPLACE FUNCTION Get_WorkingDays(
ny IN VARCHAR2
) RETURN INTEGER IS
/*-----------------------------------------------------------------------------------------
函數名稱:Get_WorkingDays
中文名稱:求某一年月中共有多少工做日
做者姓名: XINGPING
編寫時間: 2004-05-23
輸入參數:NY:所求包含工做日數的年月,格式爲yyyymm,如200405
返 回 值:整型值,包含的工做日數目。
算法描述:使用Last_day函數計算出參數所給年月共包含多少天,根據這個值來構造一個循環。在這個循環中先求這個月的每一天與一個已知是星期天的日期(2001-12-30是星期天)的差,所得的差再對7求模。若是所求日期在2001-12-30之前,那麼所得的差既是負數,求模後所得值範圍爲大於-6,小於0,如-1表示星期六,故先將求模的結果加7,再求7的模. 如過所得值不等於0和6(即不是星期六和星期天),則算一個工做日。 
----------------------------------------------------------------------------------------*/
Result INTEGER := 0;
myts INTEGER; --所給年月的天數
scts INTEGER; --某天距2001-12-30所差的天數
rq DATE;
djt INTEGER := 1; -- 
BEGIN
myts := to_char(last_day(to_date(ny,'yyyymm')),'dd'); 
LOOP 
rq := TO_date(ny||substr(100+djt,2),'yyyymmdd');
scts := rq - to_date('2001-12-30','yyyy-mm-dd');
IF MOD(MOD(scts,7)+7,7) NOT IN(0,6) THEN
Result := Result + 1;
END IF;
djt := djt + 1; 
EXIT WHEN djt>myts;
END LOOP; 
RETURN Result; 
END Get_WorkingDays;

以上兩個版本的比較

第一個版本一條SQL語句就能夠得出結果,不須要編程就能夠達到目的。但須要使用任意一張有權訪問的、記錄條數至少爲31的一張表或視圖。
第二個版本須要編程,但不須要表或者視圖。
這兩個版本都還存在須要完善的地方,即沒有考慮節日,如五1、11、元旦、春節這些節假期都沒有去除。這些節假日應該維護成一張表,而後經過查表來去除這些節假日。算法

相關文章
相關標籤/搜索