Запрос Oracle для получения количества рабочих дней между 2 датами - PullRequest
0 голосов
/ 25 января 2019

Мы используем Oracle 11.

В нашем заявлении CASE WHEN мне нужно проверить, не превышает ли число дней между двумя датами> 3 рабочих дня (исключая выходные и праздничные дни).

Итак, если

Дата1 = 21.01.19 (понедельник)

Дата2 = 18.01.19 (пятница)

Количество рабочих дней вмежду датой 1 и датой 2 - 1 день, а не 3 дня.

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

Спасибо.

Ответы [ 2 ]

0 голосов
/ 26 января 2019

Вам не нужно использовать иерархический запрос, и вы можете выполнять его независимо от настроек NLS, используя TRUNC( date_value, 'IW' ), чтобы найти начало недели ISO, которая всегда является понедельником.

( TRUNC( end_date, 'IW' ) - TRUNC( start_date, 'IW' ) ) * 5 / 7

Будетнайдите количество рабочих дней между началом недели ISO, содержащей дату начала, и началом недели ISO, содержащей дату окончания.

Затем просто добавьте рабочие дни последней недели:

+ LEAST( TRUNC( end_date   ) - TRUNC( end_date,   'IW' ) + 1, 5 )

И вычтите дни первой недели ISO перед датой начала:

- LEAST( TRUNC( start_date ) - TRUNC( start_date, 'IW' ), 5 )

Что при объединении дает:

Установка Oracle

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

Запрос :

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;

Выход :

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 здесь

0 голосов
/ 25 января 2019

Вы можете создать такую ​​функцию, которая использует conditional aggregation как

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; 

чтобы получить рабочие дни между двумя датами, включая обе пограничные даты.

т.е. он возвращает 2 для вашего случая, включая monday и friday.

Редактировать: Если вы не хотите создавать функцию, используйте следующий запрос с переменными подстановки &i_settlement_date и &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;

и введите значения выборки как date'2019-01-21' и date'2019-01-18' соответственно, когда это будет предложено.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...