如何计算Oracle中的工作日

时间:2017-10-10 07:14:50

标签: sql oracle oracle11g

我有2个表可供我使用,一个是带有start_date和end_date的main_table,另一个是holiday_table,其中标记了所有客户端假期以及周末。

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

main_table(start_date日期,end_date日期)和holiday_table(假日日期) 我有一段代码可以很容易地分开holiday_table中列出的所有假期,前提是start_date和end_date的值是硬编码的。 代码: 选择(to_date('10 / 10/2017','mm / dd / yyyy') - to_date('10 / 01/2017','mm / dd / yyyy')) - (从holiday_2016 t中选择计数(*)其中t.holidays> to_date('10 / 01/2017',

来自双重

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

但这不是我想要的,因为我有一个表,其中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和end_date中添加过滤器:

  1. 具有start_date<的请求'10 / 01/2017'和start_date> '10 / 20/2017'将被淘汰
  2. 具有end_date<的请求'10 / 01/2017'和start_date> '10 / 20/2017'也将被淘汰

1 个答案:

答案 0 :(得分: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 |