Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

adicionando dias úteis no oracle sql


Você pode tentar isso:
select max(date_field_two) as date_field_two
  from
 (
 select date'2018-08-30'+  
    cast(case when to_char(date'2018-08-30'+level,'D','NLS_DATE_LANGUAGE=ENGLISH') 
                                              in ('6','7') then 
            0
          else
            level
          end as int) as date_field_two, 
 sum(cast(case when to_char(date'2018-08-30'+level,'D','NLS_DATE_LANGUAGE=ENGLISH')  
                                               in ('6','7') then 
            0
          else
            1
          end as int)) over (order by level) as next_day
      from dual
    connect by level <= 20*1.5 
-- 20 is the day to be added, every time 5(#of business days)*1.5 > 7(#of week days)
-- 7=5+2<5+(5/2)=5*(1+1/2)=5*1.5 [where 1.5 is just a coefficient might be replaced a greater one like 2]
-- so 4*5*1.5=20*1.5 > 4*7 
  )    
 where next_day = 20;

 DATE_FIELD_TWO
-----------------
   27.09.2018

usando connect by dual cláusula.

P.S. Ignorado o caso dos feriados, que diferem de uma cultura para outra, dependendo da questão estar relacionada apenas aos finais de semana.

Demonstração do Rextester

Editar: Suponha que você tenha feriados nacionais em '2018-09-25' e '2018-09-26' (neste conjunto de dias), então considere o seguinte:
select max(date_field_two) as date_field_two
  from
 (
 select date'2018-08-30'+  
        (case when to_char(date'2018-08-30'+level,'D','NLS_DATE_LANGUAGE=ENGLISH') 
                                              in ('6','7') then 
               0
              when date'2018-08-30'+level in (date'2018-09-25',date'2018-09-26') then
               0
              else
               level
              end) as date_field_two, 
 sum(cast(case when to_char(date'2018-08-30'+level,'D','NLS_DATE_LANGUAGE=ENGLISH')  
                                               in ('6','7') then 
                0
               when date'2018-08-30'+level in (date'2018-09-25',date'2018-09-26') then
                0 
               else
                1
               end as int)) over (order by level) as next_day
      from dual
    connect by level <= 20*2 
  )    
 where next_day = 20;

 DATE_FIELD_TWO
-----------------
   01.10.2018

que itera um dia seguinte, como neste caso, a menos que este feriado coincida com o fim de semana.