查出任一年月所含的工作日

发表于:2007-06-22来源:作者:点击数: 标签:
CREATE OR REPLACE FUNCTION Get_WorkingDays( ny IN VARCHAR2 ) RETURN INTEGER IS /*------------------------------------------------------------------------------------------ 函数名称:Get_WorkingDays 中文名称:求某一年月中共有多少工作日 作者

   
  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的一张表或视图。
  
  第二个版本需要编程,但不需要表或者视图。
  
  这两个版本都还存在需要完善的地方,即没有考虑节日,如五一、十一、元旦、春节这些节假期都没有去除。这些节假日应该维护成一张表,然后通过查表来去除这些节假日。

原文转自:http://www.ltesting.net