2017-04-26 42 views
0

我有一个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;' 
+5

什么是您的DBMS? “在SQL中”?什么SQL?甲骨文? PostgreSQL的? –

+0

ANSI SQL不能将'16 -APR-11'识别为日期。你使用哪个dbms? – jarlh

回答

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标准日期和表的别名。

+0

这是一个例子。我有这个问题的原始功能是 – Ann

0

你的where子句是这样的:

where trunc(HOLIDAY_DATE) = to_date('2016-APR-11', 'yyyy-mon-dd') 
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_dateTRUNC进行比对之前进行初始化,所有的时间组件被有效忽略。)

+0

这只能算一整天 - 处理部分日子,请参阅[本答案](https://stackoverflow.com/a/44407013/1509264)中此函数的修订版。 – MT0

相关问题