用于获取除假期之外的两个日期之间的工作日数

时间:2017-04-26 11:18:12

标签: sql oracle

我有一个sql查询,它会转换2个日期并检查它们是否相等。但即使日期相同,我也不会得到结果。

create or replace 
FUNCTION getWorkingDays(
  DATE_ONE DATE,
  DATE_TWO DATE)
RETURN NUMBER
IS
DAY_COUNT  NUMBER := 0;
START_DATE DATE;
END_DATE   DATE;
HOL_COUNT NUMBER := 0;
BEGIN        
IF(DATE_ONE                   IS NOT NULL AND DATE_TWO IS NOT NULL) THEN
  IF DATE_ONE                  < DATE_TWO THEN
    START_DATE                := DATE_ONE;
    END_DATE                  := DATE_TWO;
  ELSE
    START_DATE := DATE_TWO;
    END_DATE   := DATE_ONE;
  END IF;     
  WHILE START_DATE < END_DATE       
  LOOP      
    IF TO_CHAR(START_DATE,'DY') NOT IN ('SAT','SUN') THEN
      DAY_COUNT := DAY_COUNT         + 1;
    END IF;      
     SELECT count(*) INTO HOL_COUNT
FROM ATL_JOB_HOLIDAY jh
JOIN ATL_MASTER_JOB mj
ON MJ.MASTER_JOB_ID       = JH.MASTER_JOB_ID
WHERE TRUNC(HOLIDAY_DATE) = START_DATE;
     IF(HOL_COUNT >0) THEN
      DAY_COUNT := DAY_COUNT         + 1;
       Dbms_Output.put_line('Holiday333 :- IS A HOLIDAY');
       END IF; 
        START_DATE := START_DATE + 1;       
  END LOOP;
END IF;
RETURN DAY_COUNT;
EXCEPTION
WHEN OTHERS THEN
  RETURN NULL;
END getWorkingDays;'

3 个答案:

答案 0 :(得分:0)

我猜你正在使用Oracle。如果是这样,DATE数据类型包含时间组件。这相当令人困惑。但是你可以使用TRUNC()而不是CAST()

来做你想做的事
SELECT TRUNC(HOLIDAY_DATE), DATE '2011-04-16'  --into DAY_COUNT
FROM ATL_JOB_HOLIDAY jh JOIN
     ATL_MASTER_JOB mj
     ON mj.MASTER_JOB_ID = jh.MASTER_JOB_ID
WHERE TRUNC(HOLIDAY_DATE) = DATE '2011-04-16';

还要注意ANSI标准日期和表别名的首选项。

答案 1 :(得分:0)

你的where子句是这样的:

where trunc(HOLIDAY_DATE) = to_date('2016-APR-11', 'yyyy-mon-dd')

答案 2 :(得分:0)

我在你之前的问题中发布了大部分内容。您无需循环查看每个日期并单独检查每个日期。您应该能够计算工作日数,然后只需减去表中不同日期的数量:

CREATE FUNCTION getWorkingDays (
  in_start_date IN  DATE,
  in_end_date   IN  DATE
) RETURN NUMBER
IS
  p_start_date   DATE;
  p_end_date     DATE;
  p_working_days NUMBER;
  p_holiday_days NUMBER;
BEGIN
  IF in_start_date IS NULL OR in_end_date IS NULL THEN
    RETURN NUll;
  END IF;

  p_start_date := TRUNC( LEAST( in_start_date, in_end_date ) );
  p_end_date   := TRUNC( GREATEST( in_start_date, in_end_date ) );

  -- 5/7 * ( Number of weekdays between monday of the week containing the start date
  --         and monday of the week containing the end date )
  -- + LEAST( day of week for end date, 5 )
  -- - LEAST( day of week for start date, 5 )
  p_working_days := ( TRUNC( p_end_date, 'IW' ) - TRUNC( p_start_date, 'IW' ) ) * 5 / 7
                    + LEAST( p_end_date - TRUNC( p_end_date, 'IW' ) + 1, 5 )
                    - LEAST( p_start_date - TRUNC( p_start_date, 'IW' ) + 1, 5 );

  SELECT COUNT( DISTINCT TRUNC( HOLIDAY_DATE ) )
  INTO   p_holiday_days
  FROM   ATL_JOB_HOLIDAY jh
  JOIN   ATL_MASTER_JOB mj
  ON     MJ.MASTER_JOB_ID    = JH.MASTER_JOB_ID
  WHERE  TRUNC(HOLIDAY_DATE) BETWEEN p_start_date AND p_end_date;

  RETURN p_working_days - p_holiday_days;
END;
/

(注意:HOLIDAY_DATEin_start_datein_end_date在进行比较之前会TRUNC,以便有效地忽略所有时间组件。)