Decode360's Blog

          業精于勤而荒于嬉 QQ:150355677 MSN:decode360@hotmail.com

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 ::  :: 管理 ::
            302 隨筆 :: 26 文章 :: 82 評論 :: 0 Trackbacks
          1、打印一張當月的日歷:
          ?

          select max (decode( mod (n, 7 ), 0 , m, null )) ,

          ?????? max (decode( mod (n, 7 ), 1 , m, null )) ,

          ?????? max (decode( mod (n, 7 ), 2 , m, null )) ,

          ?????? max (decode( mod (n, 7 ), 3 , m, null )) ,

          ?????? max (decode( mod (n, 7 ), 4 , m, null )) ,

          ?????? max (decode( mod (n, 7 ), 5 , m, null )) ,

          ?????? max (decode( mod (n, 7 ), 6 , m, null ))

          ? from ( select rownum m, rownum + to_char(trunc( sysdate , 'mm' ), 'd' ) - 2 n

          ????????? from dual

          ??????? connect by rownum < = to_char(last_day( sysdate ), 'dd' ))

          ? group by trunc(n / 7 )

          ? order by trunc(n / 7 );

          ?

          說明:

          1、首先通過 connect by rownum < = to_char(last_day( sysdate ), 'dd' ) 來取出當月的天數序列

          2、再用 to_char(trunc(sysdate, 'mm'), 'd')-2 來提取當天是對應星期幾

          3、通過 decode( mod (n, 7 ), 0 , m, null ) 來確定該天打印在星期幾的列中,其實mod放到第2步做思路更加清晰

          4、通過 group by trunc(n / 7 ) 來將一個星期內的天數打印到一行中

          5、雖然比較簡單,而且也沒有什么實用價值,不過這個小程序還是有一些閃光點的,比如group by,記錄一下

          ?

          ?

          ?

          2、用SQL直接取工作日:

          ?

          ?

          with t as ( select date '2008-09-01' s, date '2008-09-10' e from dual)

          select s,e,e-s+ 1 total_days,

          (length( replace (rpad(substr( '0111110' ,to_char(s, 'd' )),e-s+ 1 , '0111110' ), '0' , '' ))) work_days

          from t;

          ?

          說明:

          1、其他沒什么好說的,主要就是 (length( replace (rpad(substr( '0111110' ,to_char(s, 'd' )),e-s+ 1 , '0111110' ), '0' , '' ))) 這句了,一層層看一下

          2、substr('0111110',to_char(s,'d')) 這句的作用是找出開始日為星期幾,并將其后的每一天對應011110,0為休息日,1為工作日

          3、rpad(substr('0111110',to_char(s,'d')),e-s+1,'0111110') 將字符串填充的e-s+1的長度,且每個工作日均對應為1,休息日為0

          4、replace 的作用是把011111011111011111……中的0都刪除,留下1

          5、最后用length 統計一下字符串的長度即為工作日的天數

          6、這個方法雖然簡單,但是有一個很大的問題,就是Oracle的字符串最長只有4000個字符,也就是說,相隔時間大于4000天的,work_days 將恒等于2858而發生錯誤,所以需要進行進一步的改進

          ?

          ?

          with t as (selectdate'2008-09-01' s,date'2008-09-10' e from dual )

          select s,e,e-s+ 1 total_days,

          trunc((e-s+ 1 )/ 7 )* 5 + nvl(length( replace (substr( '01111100111110' ,to_char(s, 'd' ), mod (e-s+ 1 , 7 )), '0' , '' )), 0 ) work_days

          from t;

          ?

          說明:

          1、使用了trunc((e-s+1)/7)*5的形式,然后進行不整位的補足,就沒有了字符串長度的限制

          2、當(e-s+1)是7的倍數時,顯然工作日就是 ((e-s+1)/7)*5

          3、當(e-s+1)不被7整除是,可以理解為將最前面不能被7整除的部分mod(e-s+1,7)取出來,剩余的部分則正好為((e-s+1)/7)*5

          4、nvl(length(replace(substr('01111100111110',to_char(s,'d'),mod(e-s+1,7)),'0','')),0)就是對mod(e-s+1,7)部分的操作

          5、接下來這部分跟前一種方法的原理差不多,就是根據起始位置是星期幾,來順次往后取到工作日標記為1,休息日標記為0

          6、需要注意的是substr('0111110',n,0)結果為null,replace('0','0','')的結果也為null,此時整個修正不為結果為null,無法正確顯示結果,好在這兩種情況下后面部分的結果都是可以忽略不記的,所以在最外面套一層nvl就可以了。




          ?





          -The End-

          posted on 2008-08-30 19:21 decode360-3 閱讀(135) 評論(0)  編輯  收藏 所屬分類: SQL Dev
          主站蜘蛛池模板: 阳春市| 西充县| 尤溪县| 神木县| 岱山县| 手机| 大悟县| 南汇区| 和田县| 万盛区| 滕州市| 扶绥县| 特克斯县| 涞源县| 南澳县| 望城县| 普格县| 墨脱县| 乐亭县| 衡山县| 临海市| 井陉县| 邯郸市| 中江县| 仙游县| 宁晋县| 大兴区| 阳东县| 陈巴尔虎旗| 碌曲县| 荔波县| 平湖市| 平遥县| 惠东县| 巴里| 湄潭县| 麦盖提县| 乌兰察布市| 濮阳县| 宜宾县| 甘孜县|