Oracle query to get the number of business days between 2 dates

半世苍凉 提交于 2019-12-11 17:44:10

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!