2017-10-10 55 views
0

我有两个表可供我使用,其中一个是main_table,带有start_date和end_date,另一个是holiday_table,其中所有客户端节假日和周末都标记了。如何计算Oracle中的营业日

我需要计算从start_date到end_date的所有工作日,消除该特定持续时间内在holiday_table中发生的所有假期。

MAIN_TABLE(开始日期日期,结束日期日期)和holiday_table(节假日日期) 我有一段代码,其容易地分离在holiday_table列出的所有节假日,仅当起始日期日期和结束日期的值是硬编码的。 (选择次数(*)(日期/年月日)(日期/月/年) )from holiday_2016 t where t.holidays> to_date('10/01/2017',

'mm/dd/yyyy')and t.holidays < = to_date('10/10/2017','mm/dd/yyyy'))from dual

但是这不是我想要的,因为我有一个表,其中有不同的start_date和end_date值,因此这些值不能被硬编码。

i/p tables : 
1. main_table 
start_date end_date 
-------------------- 
10/01/2017 10/10/2017 
10/05/2017 10/20/2017 
09/29/2017 10/05/2017 

holiday_table 
holidays 
------------ 
10/01/2017 --Sunday 
10/02/2017 --Gandhi Jayanti 
10/07/2017 --Saturday 
10/08/2017 --Sunday 
10/14/2017 --Saturday 
10/15/2017 --Sunday 
10/19/2017 --Diwali 

o/p table should be like : 
start_date end_date bus_days 
------------------------------------------ 
10/01/2017 10/10/2017 06 
10/05/2017 10/20/2017 10 
09/29/2017 10/05/2017 04 

++如果此方法有效时,我需要添加过滤器来START_DATE日期和结束日期:具有START_DATE <

  1. 请求'10/01/2017' 和起始日期> '10/20/2017' 将被淘汰
  2. 请求具有END_DATE < '10/01/2017' 和起始日期> '10/20/2017' 也将消除
+1

请提供样本数据和预期结果(根据您提供的数据) –

+0

您的数据模型不清楚。假期属性的内容是什么?输出结果也不清楚。 –

+0

我已经抽出了I/P和期望的O/P表以及所提到的表的属性。让我知道,如果它仍然不清楚。 – Sam

回答

0

这种方法很适合我在过去的类似需求

select 
     t.START_DATE 
    , t.END_DATE 

    , trunc(to_number(t.END_DATE - t.START_DATE)) + 1 
    - trunc(to_number(t.END_DATE - t.START_DATE)/7) * 2 
    - (CASE WHEN to_char(t.START_DATE,'day') = 'sunday' THEN 1 ELSE 0 END) 
    - (CASE WHEN to_char(t.END_DATE,'day') = 'saturday' THEN 1 ELSE 0 END) 
    weekdays 

    , trunc(to_number(t.END_DATE - t.START_DATE)) + 1 
    - trunc(to_number(t.END_DATE - t.START_DATE)/7) * 2 
    - (select count(*) from holiday_table 
     where holidays between t.START_DATE and t.END_DATE) 
    businessdays_A 

    , trunc(to_number(t.END_DATE - t.START_DATE)) + 1 
    - trunc(to_number(t.END_DATE - t.START_DATE)/7) * 2 
    - (CASE WHEN to_char(t.START_DATE,'day') = 'sunday' THEN 1 ELSE 0 END) 
    - (CASE WHEN to_char(t.END_DATE,'day') = 'saturday' THEN 1 ELSE 0 END) 
    - (select count(*) from holiday_table 
     where holidays between t.START_DATE and t.END_DATE) 
    businessdays_B 

from main_table T 

编辑我现在已经看到了一些样本数据我不知道,如果你需要删除周末或没有。看来你可能非工作日明确存储曾经在假期表,所以你可能只需要这样:

, trunc(to_number(t.END_DATE - t.START_DATE)) + 1 
    - (select count(*) from holiday_table 
     where holidays between t.START_DATE and t.END_DATE) 
    businessdays_C 

SQL Fiddle

CREATE TABLE MAIN_TABLE 
    (START_DATE DATE, END_DATE DATE) 
; 

INSERT ALL 
    INTO main_table (START_DATE, END_DATE) 
     VALUES (TO_DATE('01-Oct-2017','dd-mon-yyyy'), TO_DATE('10-Oct-2017','dd-mon-yyyy')) 
    INTO main_table (START_DATE, END_DATE) 
     VALUES (TO_DATE('05-Oct-2017','dd-mon-yyyy'), TO_DATE('20-Oct-2017','dd-mon-yyyy')) 
    INTO main_table (START_DATE, END_DATE) 
     VALUES (TO_DATE('29-Sep-2017','dd-mon-yyyy'), TO_DATE('05-Oct-2017','dd-mon-yyyy')) 
SELECT * FROM dual 
; 

CREATE TABLE HOLIDAY_TABLE 
    (HOLIDAYS DATE, NAME varchar2(14)) 
; 

INSERT ALL 
    INTO holiday_table (HOLIDAYS, NAME) 
     VALUES (TO_DATE('01-Oct-2017','dd-mon-yyyy'), 'Sunday') 
    INTO holiday_table (HOLIDAYS, NAME) 
     VALUES (TO_DATE('02-Oct-2017','dd-mon-yyyy'), 'Gandhi Jayanti') 
    INTO holiday_table (HOLIDAYS, NAME) 
     VALUES (TO_DATE('07-Oct-2017','dd-mon-yyyy'), 'Saturday') 
    INTO holiday_table (HOLIDAYS, NAME) 
     VALUES (TO_DATE('08-Oct-2017','dd-mon-yyyy'), 'Sunday') 
    INTO holiday_table (HOLIDAYS, NAME) 
     VALUES (TO_DATE('14-Oct-2017','dd-mon-yyyy'), 'Saturday') 
    INTO holiday_table (HOLIDAYS, NAME) 
     VALUES (TO_DATE('15-Oct-2017','dd-mon-yyyy'), 'Sunday') 
    INTO holiday_table (HOLIDAYS, NAME) 
     VALUES (TO_DATE('19-Oct-2017','dd-mon-yyyy'), 'Diwali') 
SELECT * FROM dual 
; 

查询1

select 
     t.START_DATE 
    , t.END_DATE 

    , trunc(to_number(t.END_DATE - t.START_DATE)) + 1 
    - trunc(to_number(t.END_DATE - t.START_DATE)/7) * 2 
    - (CASE WHEN to_char(t.START_DATE,'day') = 'sunday' THEN 1 ELSE 0 END) 
    - (CASE WHEN to_char(t.END_DATE,'day') = 'saturday' THEN 1 ELSE 0 END) 
    weekdays 

    , trunc(to_number(t.END_DATE - t.START_DATE)) + 1 
    - trunc(to_number(t.END_DATE - t.START_DATE)/7) * 2 
    - (select count(*) from holiday_table 
     where holidays between t.START_DATE and t.END_DATE) 
    businessdays_A 

    , trunc(to_number(t.END_DATE - t.START_DATE)) + 1 
    - trunc(to_number(t.END_DATE - t.START_DATE)/7) * 2 
    - (CASE WHEN to_char(t.START_DATE,'day') = 'sunday' THEN 1 ELSE 0 END) 
    - (CASE WHEN to_char(t.END_DATE,'day') = 'saturday' THEN 1 ELSE 0 END) 
    - (select count(*) from holiday_table 
     where holidays between t.START_DATE and t.END_DATE) 
    businessdays_B 

     , trunc(to_number(t.END_DATE - t.START_DATE)) + 1 
     - (select count(*) from holiday_table 
      where holidays between t.START_DATE and t.END_DATE) 
     businessdays_C 

from main_table T 

Results

|   START_DATE |    END_DATE | WEEKDAYS | BUSINESSDAYS_A | BUSINESSDAYS_B | BUSINESSDAYS_C | 
|----------------------|----------------------|----------|----------------|----------------|----------------| 
| 2017-10-01T00:00:00Z | 2017-10-10T00:00:00Z |  8 |    4 |    4 |    6 | 
| 2017-10-05T00:00:00Z | 2017-10-20T00:00:00Z |  12 |    7 |    7 |    11 | 
| 2017-09-29T00:00:00Z | 2017-10-05T00:00:00Z |  7 |    5 |    5 |    5 | 
+0

代码工作完全正常,进行了一些必要的更改。谢谢!! – Sam

+0

'to_char(t.START_DATE,'day')='sunday''应该写成'to_char(t.START_DATE,'fmday','nls_date_language = american')='sunday''。我想知道为什么'to_char(t.START_DATE,'day')='sunday'似乎没有'fm'(或'''sunday'') –