SQL计算工作日
2013-04-11 18:09
288 查看
本文摘录了两段SQL的小技巧,来解决工作中的一些常用到的问题。主要是为了记录一下第一条,这条SQL是用来计算两个日期中的工作日的方法,从ITPUT那边看来的,很实用的一段SQL,而且用的算法很好,值得学习。当然只能剔除掉周六周日,别的法定节假日肯定就不行了。另一个是写的如何打印日历,比较白痴的一段SQL,呵呵,顺手摘录一下。 1、用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就可以了。 2、打印一张当月的日历: 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,记录一下
http://www.blogjava.net/decode360/archive/2008/08/30/282985.html
相关文章推荐
- sql如何计算两个日期间的工作日,剔除节假日
- SQL 计算两日期之间的工作天数和过滤工作日(周六、周日)
- Transact-SQL 计算工作日,不适用于oracle
- 【原创】如何使用一句SQL计算工作日天数?
- 计算时间段内的工作日的SQL_SERVER脚本
- SQL语句计算两个日期之间有多少个工作日的方法
- SQL计算实际工作日(天)及两个时间(工作日)间隔(小时)!
- SQL语句计算两个日期之间有多少个工作日的方法
- SQL计算实际工作日(天)及两个时间(工作日)间隔(小时)!
- 计算某列的字符串相加sql语句
- 计算sql语句的时间
- iModel中同表引用的Sql计算表达式书写格式
- 6.计算字段 ---SQL
- SQL 数据小练习,呼叫中心 ----查询通话时间最长的5条记录 ----查询以0开头的通话总时,以秒为计算单位 ----查询2010年7月通话总时长最多的前两个呼叫员的编号 ----查询201
- Vertica用于时间计算的SQL语句大全
- 《Microsoft SQL Server 2008 MDX Step by Step》学习笔记十一:计算成员和动态命名集
- 简化SQL计算之字母分段
- sql中取身份证字段自动计算年龄
- 计算两个日期之间的工作日(去掉周末和节假日)
- SQL 按时间段分组计算 SPT_VALUES 使用