Ecco una funzione rapida e flessibile. Puoi contare tutti i giorni della settimana in un intervallo di date.
CREATE OR REPLACE FUNCTION wfportal.cx_count_specific_weekdays(p_week_days VARCHAR2 DEFAULT 'MON,TUE,WED,THU,FRI'
, p_start_date DATE
, p_end_date DATE)
RETURN NUMBER
IS
/***************************************************************************************************************
*
* FUNCTION DESCRIPTION:
*
* This function calculates the total required week days in a date range.
*
* PARAMETERS:
*
* p_week_days VARCHAR2 The week days that need to be counted, comma seperated e.g. MON,TUE,WED,THU,FRU,SAT,SUN
* p_start_date DATE The start date
* p_end_date DATE The end date
*
* CHANGE history
*
* No. Date Changed by Change Description
* ---- ----------- ------------- -------------------------------------------------------------------------
* 0 07-May-2013 yourname Created
*
***************************************************************************************************************/
v_date_end_first_date_range DATE;
v_date_start_last_date_range DATE;
v_total_days_in_the_weeks NUMBER;
v_total_days_first_date_range NUMBER;
v_total_days_last_date_range NUMBER;
v_output NUMBER;
v_error_text CX_ERROR_CODES.ERROR_MESSAGE%TYPE;
--Count the required days in a specific date ranges by using a list of all the weekdays in that range.
CURSOR c_total_days (v_start_date DATE
, v_end_date DATE) IS
SELECT COUNT(*) total_days
FROM (SELECT (v_start_date + level - 1) days
FROM dual
CONNECT BY LEVEL <= (v_end_date - v_start_date) + 1
)
WHERE INSTR(',' || p_week_days || ',', ',' || TO_CHAR(days, 'DY', 'NLS_DATE_LANGUAGE=english') || ',', 1) > 0
;
--Calculate the first and last date range by retrieving the first Sunday after the start date and the last Monday before the end date.
--Calculate the total amount of weeks in between and multiply that with the total required days.
CURSOR c_calculate_new_dates (v_start_date DATE
, v_end_date DATE) IS
SELECT date_end_first_date_range
, date_start_last_date_range
, (
(
(date_start_last_date_range - (date_end_first_date_range + 1))
)/7
) * total_required_days total_days_in_the_weeks --The total amount of required days
FROM (SELECT v_start_date + DECODE(TO_CHAR(v_start_date, 'DY', 'NLS_DATE_LANGUAGE=english')
, 'MON', 6
, 'TUE', 5
, 'WED', 4
, 'THU', 3
, 'FRI', 2
, 'SAT', 1
, 'SUN', 0
, 0) date_end_first_date_range
, v_end_date - DECODE(TO_CHAR(v_end_date, 'DY', 'NLS_DATE_LANGUAGE=english')
, 'MON', 0
, 'TUE', 1
, 'WED', 2
, 'THU', 3
, 'FRI', 4
, 'SAT', 5
, 'SUN', 6
, 0) date_start_last_date_range
, REGEXP_COUNT(p_week_days, ',') + 1 total_required_days --Count the commas + 1 to get the total required weekdays
FROM dual
)
;
BEGIN
--Verify that the start date is before the end date
IF p_start_date < p_end_date THEN
--Get the new calculated days.
OPEN c_calculate_new_dates(p_start_date, p_end_date);
FETCH c_calculate_new_dates INTO v_date_end_first_date_range
, v_date_start_last_date_range
, v_total_days_in_the_weeks;
CLOSE c_calculate_new_dates;
--Calculate the days in the first date range
OPEN c_total_days(p_start_date, v_date_end_first_date_range);
FETCH c_total_days INTO v_total_days_first_date_range;
CLOSE c_total_days;
--Calculate the days in the last date range
OPEN c_total_days(v_date_start_last_date_range, p_end_date);
FETCH c_total_days INTO v_total_days_last_date_range;
CLOSE c_total_days;
--Sum the total required days
v_output := v_total_days_first_date_range + v_total_days_last_date_range + v_total_days_in_the_weeks;
ELSE
v_output := 0;
END IF;
RETURN v_output;
EXCEPTION
WHEN OTHERS
THEN
RETURN NULL;
END cx_count_specific_weekdays;
/
Aggiungi la soluzione come risposta in modo da poterla "accettare" (è meglio che questo sito abbia domande con risposte accettate) –