繼上次發文的討論題,下一個最接近的上旬、中旬、下旬的第一天?(ex, 9/1, 9/11, 9/21)?
乾脆發個文來說明。
為了驗證測試,以2月份的某一天來測試比較妥當,因為2月只有28天,其他大月31天的,則是直接去掉,如果程式不小心跑成2013/2/31,就會報錯啦~
開始測試文;
Select To_Number(To_Char(To_Date('20130225', 'yyyymmdd'), 'dd')) Dd From Dual;
=25
要換算出 2013/3/1,該怎麼算?
基本上,第一個處理動作就是,讓他每10天去做trunc,但是trunc可沒提供這功能吧!DIY吧!
首先,每月1-10 = 0, 11-20 = 1, 21-31 = 2;
Select Trunc(To_Number(To_Char(To_Date('20130225', 'yyyymmdd'), 'dd')-1)/10) Dd From Dual;
=2
接著讓這個結果變成10天後日期,以下用變數:Feb25替代'20130225';
Select (Trunc(To_Number(To_Char(To_Date(:Feb25, 'yyyymmdd'), 'dd')-1)/10)+1)*10 +1 Dd From Dual;
=31,但2月可沒有31日!還要再加工過。
大於31以後的都應該變成下個月1號,否則就歸零到月初+計算出的天數-1即可;
Select Decode(
((Trunc(To_Number(To_Char(To_Date(:Feb25, 'yyyymmdd'), 'dd')-1)/10)+1)*10 +1),
31, Trunc(Add_Months(To_Date(:Feb25, 'yyyymmdd'), 1), 'mm'),
Trunc(To_Date(:Feb25, 'yyyymmdd'), 'mm') + ((Trunc(To_Number(To_Char(To_Date(:Feb25, 'yyyymmdd'), 'dd')-1)/10)+1)*10 +1) - 1 ) Dd
From Dual;
=2013/3/1 OK了。測試多個日子,確認是OK的!
p.s 這種功能真的寫個pl/sql, 用package、function都好,別真的費心搞這種單一SQL,不然後人會研究老半天還未必看得懂。