问题
We are using Oracle 11.
In our CASE WHEN statement, I need to check if the number of days between the 2 dates are > 3 business days (so excluding weekends and holidays).
So, if
Date1 = 1/21/19 (Monday)
Date2 = 1/18/19 (Friday)
The number of business days in between Date1 and Date2 is 1 day, not 3 days.
CASE WHEN TO_DATE(SETTLEMENT_DATE, 'YYYY-MM-DD') - TO_DATE(TRADE_DATE,
'YYYY-MM-DD') > 3 THEN 0 --> this includes weekend and holidays
WHEN CODE = 1 THEN 1
WHEN CODE =2 THEN 2
ELSE 3
END AS MyColumn
Thank you.
回答1:
You do not need to use a hierarchical query and can do it independent of the NLS settings using TRUNC( date_value, 'IW' ) to find the start of the ISO week, which is always a Monday.
( TRUNC( end_date, 'IW' ) - TRUNC( start_date, 'IW' ) ) * 5 / 7
Will find the number of working days between the start of the ISO week containing the start date and the start of the ISO week containing the end date.
Then just add the working days of the final week:
+ LEAST( TRUNC( end_date ) - TRUNC( end_date, 'IW' ) + 1, 5 )
And subtract the days of the first ISO week before the start date:
- LEAST( TRUNC( start_date ) - TRUNC( start_date, 'IW' ), 5 )
Which when put together gives:
Oracle Setup
CREATE TABLE table_name ( start_date, end_date ) AS
SELECT DATE '2018-12-30' + LEVEL, DATE '2019-01-10'
FROM DUAL
CONNECT BY LEVEL <= 11
Query:
SELECT TO_CHAR( start_date, 'YYYY-MM-DD "("DY")"') AS start_date,
( TRUNC( end_date, 'IW' ) - TRUNC( start_date, 'IW' ) ) * 5 / 7
+ LEAST( TRUNC( end_date ) - TRUNC( end_date, 'IW' ) + 1, 5 )
- LEAST( TRUNC( start_date ) - TRUNC( start_date, 'IW' ), 5 )
AS Num_Week_Days
FROM table_name;
Output:
START_DATE | NUM_WEEK_DAYS :--------------- | ------------: 2018-12-31 (MON) | 9 2019-01-01 (TUE) | 8 2019-01-02 (WED) | 7 2019-01-03 (THU) | 6 2019-01-04 (FRI) | 5 2019-01-05 (SAT) | 4 2019-01-06 (SUN) | 4 2019-01-07 (MON) | 4 2019-01-08 (TUE) | 3 2019-01-09 (WED) | 2 2019-01-10 (THU) | 1
db<>fiddle here
回答2:
You can create such a function which uses conditional aggregation as
SQL> alter session set NLS_TERRITORY="AMERICA"
SQL> create or replace function get_working_days(
i_settlement_date tab.settlement_date%type,
i_trade_date tab.trade_date%type
) return pls_integer is
o_working_days pls_integer;
begin
select nvl(sum(case when
to_char(trade_date + level,'Dy') in ('Sat','Sun')
then 0
else 1
end ),0)
into o_working_days
from tab
where settlement_date >= trade_date
connect by level <= i_settlement_date - i_trade_date + 1;
return o_working_days;
end;
to get the working days between two date including both boundary dates.
i.e. it returns 2 for your case including monday and friday.
Edit : If you don't want to create a function, use the following query with substution variables &i_settlement_date and &i_trade_date :
select nvl(sum(case when
to_char(trade_date + level,'Dy') in ('Sat','Sun')
then 0
else 1
end ),0) as working_days
from tab
where settlement_date >= trade_date
connect by level <= &i_settlement_date - &i_trade_date + 1;
and enter the sample values as date'2019-01-21' and date'2019-01-18' respectively, whenver prompted.
来源:https://stackoverflow.com/questions/54370122/oracle-query-to-get-the-number-of-business-days-between-2-dates