Гость
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Помогите отсчитать по календарю нужное число рабочих дней / 3 сообщений из 3, страница 1 из 1
09.07.2020, 16:54
    #39977832
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите отсчитать по календарю нужное число рабочих дней
Есть календарь в виде такой структуры:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
CREATE TABLE SCHEDULE_CALENDAR
(
  SCOPE        VARCHAR2(10 BYTE)                 NOT NULL,
  YYYY         NUMBER(4)            DEFAULT 0    NOT NULL,
  MM           NUMBER(2)            DEFAULT 0    NOT NULL,
  DD           NUMBER(2)            DEFAULT 0    NOT NULL,
  D            NUMBER(1)            DEFAULT 0    NOT NULL,
  CLASS        VARCHAR2(40 BYTE)                 NOT NULL,
  DESCRIPTION  VARCHAR2(200 BYTE)
)


Здесь 0 в числовых значениях означает глобальную маску, а любое другое значение задает соответствующий элемент даты (год, месяц, день, день недели), для которого действует запись.

Например производственный календарь на 2020 год выглядит таким образом:
SCOPEYYYYMMDDDCLASSDESCRIPTIONmain0000workПрофиль по умолчаниюmain0006freeВыходной (суббота)main0007freeВыходной (воскресенье)main0110freeНовогодние каникулыmain0120freeНовогодние каникулыmain0130freeНовогодние каникулыmain0140freeНовогодние каникулыmain0150freeНовогодние каникулыmain0160freeНовогодние каникулыmain0170freeРождество Христовоmain0180freeНовогодние каникулыmain02230freeДень защитника Отечестваmain0380freeМеждународный женский деньmain0510freeПраздник Весны и Трудаmain0590freeДень Победыmain06120freeДень Россииmain01140freeДень народного единстваmain20202240freeПеренос 23.02main2020390freeПеренос 08.03main2020540freeПеренос 04.01main2020550freeПеренос 05.01main20205110freeПеренос 09.05
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
with CAL as
(
select '' as SCOPE, 0 as YYYY, 0 as MM, 0 as DD, 0 as D, '' as CLASS, 'Профиль по умолчанию' as DESCRIPTION from DUAL where 0=1
union all select 'main', 0, 0, 0, 0, 'work', 'Профиль по умолчанию' from DUAL
union all select 'main', 0, 0, 0, 6, 'free', 'Выходной (суббота)' from DUAL
union all select 'main', 0, 0, 0, 7, 'free', 'Выходной (воскресенье)' from DUAL
union all select 'main', 0, 1, 1, 0, 'free', 'Новогодние каникулы' from DUAL
union all select 'main', 0, 1, 2, 0, 'free', 'Новогодние каникулы' from DUAL
union all select 'main', 0, 1, 3, 0, 'free', 'Новогодние каникулы' from DUAL
union all select 'main', 0, 1, 4, 0, 'free', 'Новогодние каникулы' from DUAL
union all select 'main', 0, 1, 5, 0, 'free', 'Новогодние каникулы' from DUAL
union all select 'main', 0, 1, 6, 0, 'free', 'Новогодние каникулы' from DUAL
union all select 'main', 0, 1, 7, 0, 'free', 'Рождество Христово' from DUAL
union all select 'main', 0, 1, 8, 0, 'free', 'Новогодние каникулы' from DUAL
union all select 'main', 0, 2, 23, 0, 'free', 'День защитника Отечества' from DUAL
union all select 'main', 0, 3, 8, 0, 'free', 'Международный женский день' from DUAL
union all select 'main', 0, 5, 1, 0, 'free', 'Праздник Весны и Труда' from DUAL
union all select 'main', 0, 5, 9, 0, 'free', 'День Победы' from DUAL
union all select 'main', 0, 6, 12, 0, 'free', 'День России' from DUAL
union all select 'main', 0, 11, 4, 0, 'free', 'День народного единства' from DUAL
union all select 'main', 2020, 2, 24, 0, 'free', 'Перенос 23.02' from DUAL
union all select 'main', 2020, 3, 9, 0, 'free', 'Перенос 08.03' from DUAL
union all select 'main', 2020, 5, 4, 0, 'free', 'Перенос 04.01' from DUAL
union all select 'main', 2020, 5, 5, 0, 'free', 'Перенос 05.01' from DUAL
union all select 'main', 2020, 5, 11, 0, 'free', 'Перенос 09.05' from DUAL
)
select * from CAL


В CLASS задается класс дня (рабочий/нерабочий), в первой строке указывается значение класса по умолчанию, следующие две строки задают выходные дни, затем идут ежегодные праздники и наконец корректировочные записи для конкретного года.

Вот, например, календарь на текущий год:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
with CAL as (select trunc(sysdate,'Y')+ROWNUM-1 as DV from DUAL connect by level < (add_months(trunc(sysdate,'Y'),12)-trunc(sysdate,'Y')+1))
select SCOPE, CAL.DV as "DATE", MIN(CLASS) KEEP (DENSE_RANK FIRST ORDER BY decode(YYYY,0,365,0), decode(MM,0,30,0), decode(D,0,7,0), decode(DD,0,1,0)) as "CLASS"
, MIN(DESCRIPTION) KEEP (DENSE_RANK FIRST ORDER BY decode(YYYY,0,365,0), decode(MM,0,30,0), decode(D,0,7,0), decode(DD,0,1,0)) as "DESCRIPTION"
from CAL, SCHEDULE_CALENDAR
where SCOPE = 'main'
and (YYYY = 0 or to_number(to_char(CAL.DV,'YYYY')) = YYYY)
and (MM   = 0 or to_number(to_char(CAL.DV,'MM'))   = MM)
and (D    = 0 or 1+trunc(CAL.DV)-trunc(CAL.DV,'IW') = D)
and (DD   = 0 or to_number(to_char(CAL.DV,'DD'))   = DD)
group by SCOPE, CAL.DV
order by "SCOPE", "DATE"



Возникла задача, для которой мне нужно отсчитать от текущей даты плюс 3 рабочих дня (для которых CLASS='work').
Если делать в лоб, то можно просто сформировать календарь (аналогично предыдущему запросу) на +20 дней и уже по ним отсчитать 3 рабочих дня.
Но это как-то топорно. Мне кажется, что должен быть более прямой способ, основанный на аналитике и вычислениях. Но пока не соображу, откуда начать.
...
Рейтинг: 0 / 0
09.07.2020, 17:10
    #39977834
Stax
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите отсчитать по календарю нужное число рабочих дней
Alibek B.

Но это как-то топорно.

нетопорное еще ж и отрадить надо

луче сделайте ф-цию, которая бы определяла рабочий/выходной

по любому пригодится

ps
у Вас кажись на референдум выходных добавали, да и за вирус обещали

.....
stax
...
Рейтинг: 0 / 0
09.07.2020, 17:36
    #39977841
Leonid Kudryavtsev
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите отсчитать по календарю нужное число рабочих дней
Stax
да и за вирус обещали

Конституционный суд постановил, что "выходные, выходными не являются" ( C )
...
Рейтинг: 0 / 0
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Помогите отсчитать по календарю нужное число рабочих дней / 3 сообщений из 3, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]