Calculating working days including holidays between dates without a calendar table in oracle SQL

后端 未结 2 813
借酒劲吻你
借酒劲吻你 2021-01-15 05:05

Okay, so I\'ve done quite a lot of reading on the possibility of emulating the networkdays function of excel in sql, and have come to the conclusion that by far the easiest

相关标签:
2条回答
  • 2021-01-15 05:54

    There are a few ways to do this. Perhaps the simplest might be to create a CTE that produces a virtual calendar table, based on Oracle's connect by syntax, and then join it to the Assesments table, like so:

    with calendar_cte as (
    select to_date('01-01-2000')+level-1 calendar_date,
           case when to_char(to_date('01-01-2000')+level-1, 'Day') 
                    in ('Sunday   ','Saturday ') then 0
                when to_date('01-01-2000')+level-1
                    in ('03-01-2000','21-04-2000','24-04-2000','01-05-2000','29-05-2000','28-08-2000','25-12-2000','26-12-2000','01-01-2001','13-04-2001','16-04-2001','07-05-2001','28-05-2001','27-08-2001','25-12-2001','26-12-2001','01-01-2002','29-03-2002','01-04-2002','06-04-2002','03-06-2002','04-06-2002','26-08-2002','25-12-2002','26-12-2002','01-01-2003','18-04-2003','21-04-2003','05-05-2003','26-05-2003','25-08-2003','25-12-2003','26-12-2003','01-01-2004','09-04-2004','12-04-2004','03-05-2004','31-05-2004','30-08-2004','25-12-2004','26-12-2004','27-12-2004','28-12-2004','01-01-2005','03-01-2005','25-03-2005','28-03-2005','02-05-2005','30-05-2005','29-08-2005','27-12-2005','28-12-2005','02-01-2006','14-04-2006','17-04-2006','01-05-2006','29-05-2006','28-08-2006','25-12-2006','26-12-2006','02-01-2007','06-04-2007','09-04-2007','07-05-2007','28-05-2007','27-08-2007','25-12-2007','26-12-2007','01-01-2008','21-03-2008','24-03-2008','05-05-2008','26-05-2008','25-08-2008','25-12-2008','26-12-2008','01-01-2009','10-04-2009','13-04-2009','04-05-2009','25-05-2009','31-08-2009','25-12-2009','28-12-2009','01-01-2010','02-04-2010','05-04-2010','03-05-2010','31-05-2010','30-08-2010','24-12-2010','27-12-2010','28-12-2010','31-12-2010','03-01-2011','22-04-2011','25-04-2011','29-04-2011','02-05-2011','30-05-2011','29-08-2011','26-12-2011','27-12-2011') 
                    then 0 
                else 1
           end working_day
    from dual
    connect by level <= 36525 + sysdate - to_date('01-01-2000') )
    SELECT a.ASM_ID,
           a.ASM_START_DATE,
           a.ASM_END_DATE,
           sum(c.working_day) AS Week_Day
    From O_ASSESSMENTS a
    join calendar_cte c 
      on c.calendar_date between a.ASM_START_DATE and a.ASM_END_DATE
    WHERE a.ASM_QSA_ID  IN ('TYPE1') and 
          a.ASM_END_DATE >= '01/01/2012' -- and a.ASM_ID = 'A00000'
    GROUP BY
          a.ASM_ID,
          a.ASM_START_DATE,
          a.ASM_END_DATE
    

    This will produce a virtual table populated with dates from 01 January 2000 to 10 years after the current date, with all weekends marked as non-working days and all days specified in the second in clause (ie. up to 27 December 2011) also marked as non-working days.

    The drawback of this method (or any method where the holiday dates are hardcoded into the query) is that each time new holiday dates are defined, every single query that uses this approach will have to have those dates added.

    0 讨论(0)
  • 2021-01-15 05:57

    If you can't use a calendar table in Oracle, you might be better off exporting to Excel. Brute force always works.

    Networkdays() "returns the number of whole working days between start_date and end_date. Working days exclude weekends and any dates identified in holidays."

    Excluding weekends seems fairly straightforward. Every 7-day period will contain two weekend days. You'll just need to take some care with the leftover days.

    Holidays are a different story. You have to either store them or pass them as an argument. If you could store them, you'd store them in a calendar table, and your problem would be over. But you can't do that.

    So you're looking at passing them as an argument. Off the top of my head--and I haven't had any tea yet this morning--I'd consider a common table expression or a wrapper for a stored procedure.

    0 讨论(0)
提交回复
热议问题