oracle 日期相減 轉載

夜色狼發表於2014-08-01
 

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

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中時間運算

內容如下: 
1、oracle支援對日期進行運算 
2、日期運算時是以天為單位進行的 
3、當需要以分秒等更小的單位算值時,按時間進位制進行轉換即可 
4、進行時間進位制轉換時注意加括號,否則會出問題

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的一張表或檢視。
第二個版本需要程式設計,但不需要表或者檢視。
這兩個版本都還存在需要完善的地方,即沒有考慮節日,如五一、十一、元旦、春節這些節假期都沒有去除。這些節假日應該維護成一張表,然後通過查表來去除這些節假日。

相關文章