`

oracle 一段时间内有几个工作日(天数)

阅读更多

create or replace
FUNCTION GETWORKDAY3
( sdate IN DATE
, edate IN DATE
) RETURN NUMBER AS
 holidays number:=0;
 st Date;
 en Date;
BEGIN
 for h in (select holiday_id hid from T_ATTE_HOLIDAYS) loop
    select DATE_START into st from T_ATTE_HOLIDAYS where holiday_id=h.hid;
    select DATE_END into en from T_ATTE_HOLIDAYS where holiday_id=h.hid;
   
    if(st>sdate and en>edate and edate>=st) then
      begin
      holidays:=(edate-st)+1+holidays-workend(st,edate);
    -- holidays:=(st-sdate)-workend(sdate,st)+holidays;
       dbms_output.put_line('left'||to_char(edate-st));
      end;
      Elsif(st<=sdate and en>edate) then
        begin
        holidays:=(edate-sdate)+1-workend(edate,sdate)+holidays;
      --  holidays:=(st-sdate)+(en-edate)+holidays-workend(sdate,st)-workend(edate,en);
         dbms_output.put_line('midder');
        end;
      Elsif(st<sdate and en<edate and sdate<en) then
        begin
        holidays:=(en-sdate)+1-workend(sdate,en)+holidays;
       -- holidays:=(edate-en)-workend(en,edate)+holidays;
         dbms_output.put_line('right');
        --  dbms_output.put_line(to_char(st,'yyyy-MM-dd')||'<'||to_char(sdate,'yyyy-MM-dd')||' and '||to_char(en,'yyyy-MM-dd')||'<'||to_char(edate,'yyyy-MM-dd'));
        end;
      Elsif(st>=sdate and en<=edate) then
        begin
        holidays:=(en-st)-workend(st,en)+1+holidays;
      -- holidays:=(st-sdate)+(edate-en)-workend(sdate,st)-workend(en,edate)+holidays;
         dbms_output.put_line('outer'||to_char(en-st)||to_char(workend(st,en)));
        end;
      else
        begin
        holidays:=0+holidays;
      -- holidays:=(edate-sdate)+1-workend(sdate,edate);
         dbms_output.put_line('else');
        end;
      end if;
     
  end loop;
  RETURN (edate-sdate)+1-holidays-workend(sdate,edate);
 --return holidays;
END GETWORKDAY3;

create or replace FUNCTION WORKEND
( sdate IN DATE
, edate IN DATE
) RETURN NUMBER AS
v_date Date;
v_days number:=0;
BEGIN
    v_date:=sdate;
  while v_date<=edate loop
    if to_char(v_date,'d') in ('1','7') then
      v_days:=v_days+1;
    end if;
    v_date:=v_date+1;
  end loop;
  return v_days;
END WORKEND;

 

------------------------第二种方法---------------------------------------------------------

create or replace
FUNCTION F_GETWORKDAY( BDATE_ IN DATE, EDATE_ IN DATE) RETURN NUMBER AS
/*************************************************************************************************************************
 * 功能:
 *    计算两个日期点之间的工作日的个数
 *
 * 参数:
 *    BDATE: 开始日期
 *    EDATE: 结束日期
 *
 * 返回值:
 *    返回工作日的个数
 *
 * 作者&时间:
 *    周继伟,2010年03月10日
 *
 * 修改:
 *    第1次:[某人]于[时间],[原因]
 *    第2次:[某人]于[时间],[原因]
 *    第3次:[某人]于[时间],[原因]
 *    第4次:[某人]于[时间],[原因]
 *    第5次:[某人]于[时间],[原因]
 *
 *************************************************************************************************************************/ 

  TYPE holiday_type IS TABLE OF VARCHAR(10) INDEX BY BINARY_INTEGER;
  unworkdays holiday_type;/*申请非工作日内存表变量*/
 
  TYPE holiday_record_type IS RECORD (sdate DATE,edate DATE);
  holiday_record holiday_record_type;/*存储从表中取出设置好的单条节假日*/
 
  CURSOR cur_holiday IS SELECT HOLIDAY_BDATE,HOLIDAY_EDATE from T_HOLIDAY;
 
  datetmp DATE;
  bWorkDay BOOLEAN DEFAULT TRUE;
  i NUMBER DEFAULT 0;
  iRtn NUMBER DEFAULT 0;
 
BEGIN
 
  /*验证,如果开始日期或工作日数为空,则直接返回NULL*/                 
  IF BDATE_ IS NULL OR EDATE_ IS NULL THEN RETURN 0; END IF;

/*将所有的非工作日存储在临时内存表中*/   
  OPEN cur_holiday;
    IF cur_holiday%ISOPEN THEN
      LOOP
        <<mycontinue1>>
        FETCH cur_holiday INTO holiday_record;
       
        EXIT WHEN cur_holiday%NOTFOUND;
       
        IF holiday_record.sdate IS NULL OR holiday_record.edate IS NULL THEN GOTO mycontinue1;  END IF;
       
        IF holiday_record.sdate <= holiday_record.edate THEN
          WHILE holiday_record.sdate <= holiday_record.edate
          LOOP
            unworkdays(i) := TO_CHAR(holiday_record.sdate,'MM-dd');
            holiday_record.sdate := holiday_record.sdate + 1;
            i := i + 1;
          END LOOP;
        END IF;
       
      END LOOP;
    END IF;
  CLOSE cur_holiday;
 
  datetmp := BDATE_;
 
  WHILE datetmp <= EDATE_
  LOOP
    IF TO_CHAR(datetmp,'d') IN (1,7) THEN
      bWorkDay := FALSE;
      GOTO mycontinue2;
    END IF;
   
    IF bWorkDay THEN
      IF unworkdays.LAST IS NOT NULL THEN
        FOR j IN 0..unworkdays.LAST LOOP
          IF TO_CHAR(datetmp,'MM-dd') = unworkdays(j) THEN
            bWorkDay := FALSE;
            GOTO mycontinue2;
          END IF;
        END LOOP;
      ELSE
        bWorkDay := FALSE;
      END IF;
    END IF;
   
    <<mycontinue2>>
    IF bWorkDay THEN iRtn := iRtn + 1; END IF;
   
    datetmp := datetmp + 1;
    bWorkDay := TRUE;
   
  END LOOP;
   
  RETURN iRtn;
END F_GETWORKDAY;

 

-----------------------------------------第三种方法------------------------------------------------

create or replace function te2(startdate in date, enddate in date) return integer is
  rs integer;
  counts integer; --两日期间的天数
  yunum integer; --余数
  weeknum integer; --星期几
  yk integer; --余数中有几天周末
begin
  select floor(enddate-startdate) into counts from dual; --不包括enddate这一天
  counts:=counts+1; --//包括enddate这一天(加1)
  rs:=counts;
  yk:=0;

  select mod(counts,7) into yunum from dual;
  select to_number(to_char(startdate,'D')) into weeknum from dual;
  if yunum>0 then
     begin
           if weeknum=6 then
              begin
                  if yunum>1 then yk:=2;
                  else yk:=1;
                  end if;
               end;
           elsif weeknum=1 then                         --注意不是elseif
                 yk:=1;
           else
               begin
                 yk:=yunum-(7-weeknum);
                 if yk<0 then
                     yk:=0;
                  end if;
               end;
         end if;
       end;
     end if;

  rs:=rs-floor(rs/7) *2-yk; --//注意integer 类型的rs/7
  return rs;
end te2;

 

把if/elsif改成case:

case weeknum
           when 6 then
              begin
                  if yunum>1 then yk:=2;
                  else yk:=1;
                  end if;
               end;
           when 1 then
                yk:=1;
           else
               begin
                 yk:=yunum-(7-weeknum);
                 if yk<0 then
                     yk:=0;
                  end if;
               end;
       end case;

分享到:
评论

相关推荐

    Oracle计算连续天数,计算连续时间,Oracle连续天数统计

    这段代码先创建了一个带有`prev_date`和`next_date`的CTE(公共表表达式),然后通过`CASE`语句判断连续性,计算连续天数。 4. **使用集合操作** 还可以通过集合操作如`MINUS`或`EXCEPT`找出连续日期的序列。这种...

    计算两个日期之间周末的天数和工作日天数

    本人编写,通过自己定义的函数计算两个日期之间周末的天数和工作日天数,经过测试,非常好用

    oracle语句查询两个日期之间星期六、星期日的天数

    oracle语句查询两个日期之间星期六、星期日的天数

    oracle函数得到下一个法定工作日期

    一个简单的方法是通过创建一个包含所有公休日(如新年、春节、国庆等)的表,然后查询这个表以确定下一个非节假日的工作日。下面是一个可能的表结构: ```sql CREATE TABLE holidays ( holiday_date DATE PRIMARY ...

    Oracle–查询时间段内执行的sql、Produce

    1.查询时间段内执行的sql、Produce select * from v$sqlarea a where 1=1 and a.LAST_ACTIVE_TIME &gt;= to_date( '2013-02-21 18:23:00','yyyy-MM-dd HH24:mi:ss') and a.LAST_ACTIVE_TIME &lt; to_date( '2013-...

    oracle sql计算一段时间内(除去周六日)的秒数

    利用 oracle sql 实现 计算一段时间内(除去周六日)的秒数

    oracle工作日设置.sql

    通过简单的设置,可查询工作日相关信息。如:今天是本月第几个工作日,今天是本年度第几个工作日,今天之后第N个工作日是哪天,之前的第N个工作日是哪天等。对计算同比,环比,限时办结等需求帮助很大。

    2023年日历(标记工作日,节假日,调休,周末),计算两个日期相差的工作日天数

    压缩包里有2个文件,用于计算两个日期相差的工作日天数(排除周末和法定节假日): 1、excel表为2023年日历数据,并且备注工作日、周末,调休、节假日类型,可导入数据库。 2、SQL文件为2023年所有日期的插入SQL,并...

    sql查询oracle时间段操作

    例如,如果你有一个名为`orders`的表,其中包含`order_date`列,你可以这样查询2020年1月1日至2020年12月31日之间的订单: ```sql SELECT * FROM orders WHERE order_date BETWEEN DATE '2020-01-01' AND DATE '...

    oracle返回相差的天数

    例如,若有一个日期字符串 `'2004/10/12'`,希望将其转换为日期类型,则可以使用如下SQL语句: ```sql SELECT TO_DATE('2004/10/12', 'yyyy/mm/dd') FROM DUAL; ``` 这里,`'yyyy/mm/dd'` 是指定了日期格式的字符...

    计算2个日期相差天数、去除节假日周末

    2. 遍历这个天数范围内的每一天,检查是否为工作日。 3. 如果是工作日(即不是周末和节假日),计数器加一。 4. 返回工作日总数。 注意,如果日期范围跨越了多个年份,还需要考虑闰年的情况,因为闰年的2月份有29天...

    Oracle 导出某时间段AWR与ASH性能报告操作日志

    ### Oracle 导出某时间段AWR与ASH性能报告操作日志 #### 一、Oracle AWR与ASH简介 ##### 1.1 AWR (Automatic Workload Repository) 在Oracle数据库环境中,AWR是一种自动化的工具,它收集并存储有关数据库工作...

    使用Oracle的SQL函数实现工作日和节假日分组统计.pdf

    使用Oracle的SQL函数实现工作日和节假日分组统计 本文介绍了使用Oracle的SQL函数来实现工作日和节假日的分组统计,通过对工作日和节假日的判断和统计,可以更好地合理调度人力物力资源,制定节假日劳务补贴政策。...

    oracle抓取指定时间段AWR报告实例说明 .docx

    通过上述步骤,我们可以有效地抓取指定时间段内的Oracle AWR报告,并对其进行全面细致的分析,从而提高数据库的整体性能。此外,对于那些频繁出现性能问题的场景,定期生成AWR报告并进行常规分析也是十分必要的。 ...

    计算两个日期相隔天数并减去节假日

    计算两个日期相隔天数并减去节假日,这个可以使用在各种需要通知的场景以及工作日提醒等

    Oracle统计一天内每小时的数据量

    Oracle统计一天内每小时的数据量。在某小时内有数据,该时间段会被统计出来;该时间段内没有交易,该时间段不会被统计出来,默认为0即可

    备份oracle数据库并保留指定天数(day)的备份文件(rar)

    除了上述基本功能外,还需要实现一个扩展功能——自动清理过期备份文件。虽然原脚本中并未提供具体实现方式,但我们可以结合Windows批处理语言中的其他命令(如`FORFILES`)来完成这一任务。 - **使用`FORFILES`...

    oracle查询一个月之内数据

    根据提供的标题、描述、标签及部分内容,我们可以了解到本篇文章主要关注的是如何在Oracle数据库中查询一个月内的数据。这里的关键在于日期范围的确定以及如何利用Oracle的内置函数来完成这一任务。接下来,我们将...

    SQL工作日计算,只排除周末

    下面详细解释了如何实现一个SQL函数来计算两个日期之间的有效工作日数量,仅排除周末。 ```sql USE [UnderWritting] GO /****** Object: UserDefinedFunction [dbo].[fn_WorkDay] ScriptDate: 02/20/2013 17:32:07 ...

    Oracle数据库按时间进行分组统计数据的方法

    对于按时间段分组查询,可以创建一个包含多个时间点的子查询,然后用`JOIN`操作与原始数据表合并,实现特定时间段内的数据统计。例如,如果要查询过去10天的数据,可以构建一个递归查询来生成过去10天的日期范围,...

Global site tag (gtag.js) - Google Analytics