1 ORACLE中周相關知識描述
1.1 日期格式化函數
TO_CHAR(X [,FORMAT]):將X按FORMAT格式轉換成字串。X是一個日期,FORMAT是一個規定了X採用何種格式轉換的格式字串,FORMAT與周相關的有W,WW,IW,D,FMWW。
W 的含義是一個月的第幾周。是按照ORACLE自訂的標準周來返回周數。
IW是ISO標準周,它的含義是ISO標準周以周別為“主線”,每年最多可以有53個周別,但是每年至少要包含52個周別;如果一年當中第52周別之後至當年的12月31日之間,還有大於或等於4天的話,則定為當年的第53周,否則剩餘這些天數被歸為下一年的第1周;如果在不足52周別的話,則以下一年的時間來補;每周固定的從周一開始作為本周的第1天,到周日作為本周的第7天;比如:在Oracle中 2012年01月01號依然屬於IW周別2011年的第52周的第7天。這個用到的比較多。
WW是ORACLE自訂的標準周,它的含義是每年的1月1日作為當年的第一周的第一天(不管當年的1月1日是星期幾);比如:2014年01年01是周三,在Oracle中被定義為2014年WW的第一周的第一天。一般很少用到。
D是返回當前日期是這個星期的第幾天。是按照從周日到周六來進行計算的,這是要注意的地方。
FMWW該年1月1號(不考慮屬星期幾)開始至該年該一個星期日為第一周,第二周是從該年第一個星期開始算(這與IW演算法相同)一年的最後一周以該年的12月31號做為截止。
1.2 日期時間運算函數
NEXT_DAY(X,Y):用於計算X時間後第一個星期Y的時間。Y是一個字串,表示用當前會話語言表示的一周中某一天的全稱(如星期一、星期二等),也可以是數值。
TRUNC(X [,FORMAT]):截斷日期, FORMAT 中與周相關的有D,IW,WW,W,FMWW。
W 的含義是一個月的第幾周。是按照ORACLE自訂的標準周來返回的是一個周數。
IW是ISO標準周,返回是的當前日期所在周的周一。
WW是ORACLE自訂的標準周。返回ORACLE自訂標準周所在的周一。
D 的含義是的返回當前星期的第一天。令人感到奇怪的是根據D返回的是當前星期的第一天是星期日。這點是我們要注意的地方。
FMWW該年1月1號(不考慮屬星期幾)開始至該年該一個星期日為第一周,第二周是從該年第一個星期開始算(這與IW演算法相同)一年的最後一周以該年的12月31號做為截止。取周的開始時間時在跨年的時候與IW有些區別,比如2012年01年01使用FMWW的時候,周的開始時間是2012-01-01,使用IW時,周的開始時間是2011/12/26。
ROUND(X [,FORMAT]):日期的四捨五入FORMAT中與周相關的有DAY。按周一到周三和周四到周日四捨五入到最近的周日。
2 根據給定時間取一周的開始時間和結束時間
--取周的開始時間和結束時間SELECT TRUNC(TO_DATE('2014-07-18','YYYY-MM-DD'),'IW') AS STARTDATE FROM DUAL;--本周周一SELECT TRUNC(TO_DATE('2014-07-18','YYYY-MM-DD'),'IW') + 6 AS ENDDATE FROM DUAL;--本周周日SELECT TRUNC(TO_DATE('2014-07-18','YYYY-MM-DD'),'IW') - 7 AS STARTDATE FROM DUAL;---上周周一 SELECT TRUNC(TO_DATE('2014-07-18','YYYY-MM-DD'),'IW') - 1 AS ENDDATE FROM DUAL;--上周周日
3 根據給定周數取一周的開始時間和結束時間
取自然周的開始時間和結束時間的痛點就需要判斷年初的那幾天是屬於本年的第一周,還是屬於上一年的最後一周,根據IW自然周的定義,少於等於3天是本年的話,屬於上一年的最後一周,大於等於4天屬於本年的話,加上上年的最後幾天,算成本年的第一周。
--按照周一到周日為一周算周的開始時間和結束時間(IW)自然周WITH PARAMS AS (SELECT TRUNC(TO_DATE('2009-01-01','YYYY-MM-DD'),'YYYY') AS SD FROM DUAL)SELECT LEVEL 周次,DECODE(SIGN(5-DECODE(TO_CHAR(PM.SD,'D'),'1','7',TO_CHAR(PM.SD,'D'))),-1,NEXT_DAY(PM.SD+(LEVEL-1)*7,2),NEXT_DAY(PM.SD+(LEVEL-1)*7-7,2)) 當周第一天,DECODE(SIGN(5-DECODE(TO_CHAR(PM.SD,'D'),'1','7',TO_CHAR(PM.SD,'D'))),-1,NEXT_DAY(PM.SD+(LEVEL-1)*7,2),NEXT_DAY(PM.SD+(LEVEL-1)*7-7,2)) + 6當周最後一天FROM DUAL DLEFT JOIN PARAMS PM ON 1=1CONNECT BY LEVEL<=53--按照周日到周六為一周算周的開始時間和結束時間(D)SELECT LEVEL 周次,(TRUNC(TO_DATE('2011-01-01','YYYY-MM-DD'),'YYYY')-7) + (7-TO_CHAR(TRUNC(TO_DATE('2011-01-01','YYYY-MM-DD'),'YYYY'),'D')+1)+(LEVEL-1)*7 當周第一天, (TRUNC(TO_DATE('2011-01-01','YYYY-MM-DD'),'YYYY')-7) + (7-TO_CHAR(TRUNC(TO_DATE('2011-01-01','YYYY-MM-DD'),'YYYY'),'D')+1)+(LEVEL-1)*7+6 當周最後一天FROM DUAL CONNECT BY LEVEL<=53--按照ORACLE標準(WW)SELECT LEVEL 周次,TO_DATE('2013-01-01','YYYY-MM-DD')+(LEVEL-1)*7 當周第一天, TO_DATE('2013-01-01','YYYY-MM-DD')+(LEVEL-1)*7+ DECODE((TO_CHAR(TO_DATE('2013-12-31','YYYY-MM-DD'),'DDD')-(LEVEL-1)*7),1,0,2,1,6) 當周最後一天FROM DUAL CONNECT BY LEVEL<=53
4 擷取一年的最大周次
--擷取一年中的最大周次(IW)中國日曆自然周WITH PARAMS AS (SELECT '2014' AS NF FROM DUAL)SELECT TO_CHAR(TO_DATE(PM.NF || '-12-28','YYYY-MM-DD'),'IYYYIW') FROM DUAL LEFT JOIN PARAMS PM ON 1=1
上述SQL通過卡每年的12月28號屬於哪個周,也判斷一年有多少個自然周。
5 特別應該注意的地方
取周別的時候最好把年份帶上,第一因為周別是相對於哪年的第幾周,第二因為當使用IW的時候對於一年的開始那幾天和結束那幾天可能會產生一樣的周數,就分不清屬於哪年的第一周。