powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Вычисление числа рабочих дней между двумя датами
17 сообщений из 17, страница 1 из 1
Вычисление числа рабочих дней между двумя датами
    #32754953
misha_22
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Нужна помощь.
Задача следующая...

С помощью простых операций написать SQL выражение для вычисления числа рабочих дней между двумя датами(субботы и воскресения не считать).

d1 date;
d2 date;

Использовать функции.
TRUNC( d2 - d1 ) - число дней между датами
TRUNC( d1, 'D' ) - окруление на начало недели
TRUNC( d1, 'MM' ) - окруление на начало месяца

LEAST ( a, b ) - наименьшее значение
GREATEST ( a, b ) - наибольшее значение
...
Рейтинг: 0 / 0
Вычисление числа рабочих дней между двумя датами
    #32754991
AlexKulikov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
так пойдет?
select sum(case when to_char(trunc(sysdate)-rownum,'d') in (1,7) then 0 else 1 end) from all_objects where rownum<=trunc(sysdate)-trunc(sysdate-15)
...
Рейтинг: 0 / 0
Вычисление числа рабочих дней между двумя датами
    #32754995
_Nikotin_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Например,

Код: plaintext
1.
2.
3.
4.
select count(*)
from
(select to_char(:start_date+ t.r,'DY') dy
 from (select rownum- 1  r from dba_objects where rownum<=(select trunc(sysdate)-:start_date+ 1  from dual)) t) d
where d.dy not in ('SUN','SAT')
...
Рейтинг: 0 / 0
Вычисление числа рабочих дней между двумя датами
    #32755025
Leonid_B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Обсуждалось и не раз. STFW , в то числе у Кайта.
Приведенные запросы не учитывают праздничные дни.
...
Рейтинг: 0 / 0
Вычисление числа рабочих дней между двумя датами
    #32755055
kh_art
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
select count(*)
from (select to_date('01.01.2004','dd.mm.yyyy')+rownum dat,
to_char(to_date('01.01.2004','dd.mm.yyyy')+rownum,'DY') dy
from sys.all_objects)
where dat<=to_date('01.01.2005','dd.mm.yyyy') and dy not in('SAT','SUN')
...
Рейтинг: 0 / 0
Вычисление числа рабочих дней между двумя датами
    #32755109
AlexKulikov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Leonid_BОбсуждалось и не раз. STFW , в то числе у Кайта.
Приведенные запросы не учитывают праздничные дни.

Само собой не учитываются праздники, а так же переносы, которые установлены законодательством на текущий год, но если это учитывать, то надо еще написать интерфейс для ведения праздников и переносов, купить лицензию на консультант или гарант, в общем это уже не "простое SQL предложение" суть как я понял, просто посчитать количество понедельников- пятницев в период между датами. единственно смущает ограничение по операторам, может это лаба, и нужно обойтись перечисленным набором операторов.... а на счет праздников - в связи с переносом рабочим может назначиться суббота или воскресенье, а в постановке четко сказано не считать сбт и вск, следовательно к праздникам привязки нет :)
...
Рейтинг: 0 / 0
Вычисление числа рабочих дней между двумя датами
    #32755349
misha_22
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо.
Да, верно, надо подсчитать только количествово дней с понедельника по пятницу.
...
Рейтинг: 0 / 0
Вычисление числа рабочих дней между двумя датами
    #32825601
_Nikotin_Например,

Код: plaintext
1.
2.
3.
4.
select count(*)
from
(select to_char(:start_date+ t.r,'DY') dy
 from (select rownum- 1  r from dba_objects where rownum<=(select trunc(sysdate)-:start_date+ 1  from dual)) t) d
where d.dy not in ('SUN','SAT')


Та же задача, понравился/работает вариант, но...
На для юзеров выдает invalid table. Как его перипесать не используя системную таблицу(вью)?
...
Рейтинг: 0 / 0
Вычисление числа рабочих дней между двумя датами
    #32825647
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Факир, замени dba_objects на любой набор данных, имеющий достаточное количество строк. В первом приближении - на all_objects.
См. также select натуральный ряд
...
Рейтинг: 0 / 0
Вычисление числа рабочих дней между двумя датами
    #32825686
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Well, you can either use function TRUNC and some driver table (data_dictionary or "select натуральный ряд", or whatever else you have) and both readability and performance wise it would be best solution. Or you can function NEXT_DAY, some math and table dual:

NEXT_DAY(start_date - 1,'SUNDAY') is first sunday >= start_date. NEXT_DAY(end_date - 7,'SUNDAY') is last Sunday <= end_date. Therefore:

(NEXT_DAY(end_date - 7,'SUNDAY') - NEXT_DAY(start_date - 1,'SUNDAY')) / 7 + 1

is number of Sunday's between start_date and end_date. Same way:

(NEXT_DAY(end_date - 7,'SATURDAY') - NEXT_DAY(start_date - 1,'SATURDAY')) / 7 + 1

As a result, number of weekdays between start_date and end_date is:

end_date - start_date + 1 -((NEXT_DAY(end_date - 7,'SUNDAY') - NEXT_DAY(start_date - 1,'SUNDAY')) / 7 + 1 + (NEXT_DAY(end_date - 7,'SATURDAY') - NEXT_DAY(start_date - 1,'SATURDAY')) / 7 + 1)

or

end_date - start_date - 1 -(NEXT_DAY(end_date - 7,'SUNDAY') - NEXT_DAY(start_date - 1,'SUNDAY')) / 7 - (NEXT_DAY(end_date - 7,'SATURDAY') - NEXT_DAY(start_date - 1,'SATURDAY')) / 7

or:

SELECT end_date - start_date - 1 -(NEXT_DAY(end_date - 7,'SUNDAY') - NEXT_DAY(start_date - 1,'SUNDAY')) / 7 - (NEXT_DAY(end_date - 7,'SATURDAY') - NEXT_DAY(start_date - 1,'SATURDAY')) / 7 FROM DUAL;

SY.
P.S. The above assumes число рабочих дней между двумя датами includes both start and end dates.
...
Рейтинг: 0 / 0
Вычисление числа рабочих дней между двумя датами
    #32826604
Эс Вай мой кумир!
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
Вычисление числа рабочих дней между двумя датами
    #40048828
dmitryk1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Эй, если кому вдруг понадобится, нате:

Код: sql
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.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
SELECT 
  d_start,
  d_end,
  ((DT.vs_all/7)*5)-w_day_start+w_day_end_wo_sat work_days, -- 1 - добавляет "включительно" дате окончания, 
                                                      --  вычитаются рабочие дни до запрошенной даты начала 
                                                      --  и добавляются рабочие дни после воскресенья перед датой окончания
                                                      --  праздники не учитываются.

-- контрольные значения 
  DT.VS_START "воскресенье перед датой начала",
  DT.d_start "Дата начала",
  DT.VS_END "Воскресенье перед окончанием",
  DT.d_end "Окончание",
  DT.W_DAY_START "Рабочих дней до начала",
  DT.VS_ALL "Дней между воскресеньями",  
  DT.W_DAY_END_WO_SAT "С воскрес. до конца(без суб)"
from
    (
     SELECT 
        (TRUNC(d_start,'d')) vs_start, -- воскресенье перед датой начала
        d_start,--даты начала и окончания периода вычисления
        (TRUNC(d_end,'d')) vs_end, -- воскресенье перед датой окончания
        d_end,--даты начала и окончания периода вычисления
        GREATEST(d_start-(TRUNC(d_start,'d'))-1,0) w_day_start, -- дней с воскресенья до начальной даты (исключаем воскресенье и получаем только рабочие дни)
        (TRUNC(d_end,'d'))-(TRUNC(d_start,'d')) vs_all, --количество дней между двумя воскресеньями
        LEAST(d_end-(TRUNC(d_end,'d')),5) w_day_end_wo_sat  -- дней с воскресенья до последней даты без учёта субботы (для этого 6 заменяем на 5, или берём что меньше)

    FROM 
        (
        SELECT
            LEAST( d_1, d_2 ) d_start,
            GREATEST(d_1, d_2) d_end
          from
              (SELECT trunc(to_timestamp(:start_date_,'DD.MM.YYYY'))  AS d_1, 
                      trunc(to_timestamp(:end_date_,'DD.MM.YYYY')) AS d_2 
                    FROM dual
              ) dt0
        )dt1
    
    )dt
  



Это до меня на собеседовании ... надо им, ..., сделать выражение.
Надеюсь это поможет кому.
Заодно, может, ошибки найдёте...

А это то, что все предлагают:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
SELECT 
  SUM(wd)
 FROM (
        SELECT to_timestamp(:start_date_,'DD.MM.YYYY') + LEVEL-1 d,
              (CASE when to_char(to_timestamp(:start_date_,'DD.MM.YYYY') + LEVEL-1,'d')IN (7,1)
                  tHEN 0 ELSE 1 end
               )wd,
            (LEVEL-1) lvl
              FROM dual
              CONNECT BY to_timestamp(:start_date_,'DD.MM.YYYY') + (LEVEL-1)  <=to_timestamp(:end_date_,'DD.MM.YYYY')
)dt
...
Рейтинг: 0 / 0
Вычисление числа рабочих дней между двумя датами
    #40048833
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dmitryk1,

cубота выходной?
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
33                 (SELECT trunc(to_timestamp('26.02.2021','DD.MM.YYYY'))  AS d_1,
 34                         trunc(to_timestamp('27.02.2021','DD.MM.YYYY')) AS d_2
 35                       FROM dual
 36                 ) dt0
 37           )dt1
 38*     )dt
SQL> /

D_START    D_END       WORK_DAYS
---------- ---------- ----------
26.02.2021 27.02.2021          2



ps
1,7 зависит от нлс

.....
stax

......
stax
...
Рейтинг: 0 / 0
Вычисление числа рабочих дней между двумя датами
    #40048846
dmitryk1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stax
dmitryk1,

cубота выходной?

ps
1,7 зависит от нлс


Это да. Забыл уточнить. Но основное было в первом куске кода. Второй - это так, собрать способы в кучу.

Так вот, к верхней формуле есть замечания?
(надеюсь я не ошибся)

На всякий - вот, в голом виде(то же что сверху):
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
SELECT 
  ((((TRUNC(GREATEST(d_1, d_2),'d'))-(TRUNC(LEAST( d_1, d_2 ),'d')))/7)*5)-(GREATEST(LEAST( d_1, d_2 )-(TRUNC(LEAST( d_1, d_2 ),'d'))-1,0))+(LEAST(GREATEST(d_1, d_2)-(TRUNC(GREATEST(d_1, d_2),'d')),5)) "Рабочих дней"
from
    (
     SELECT trunc(to_timestamp(:start_date_,'DD.MM.YYYY'))  AS d_1, 
                      trunc(to_timestamp(:end_date_,'DD.MM.YYYY')) AS d_2 
                    FROM dual
    )dt
...
Рейтинг: 0 / 0
Вычисление числа рабочих дней между двумя датами
    #40048944
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dmitryk1,

у многих

Код: plsql
1.
2.
3.
4.
5.
6.
  1* select to_char(date '2021-02-28','d') d from dual
SQL> /

D
-
7



....
stax
...
Рейтинг: 0 / 0
Вычисление числа рабочих дней между двумя датами
    #40049084
zeon11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dmitryk1,
Эта задача не имеет практического универсального решения средствами SQL. Может этого понимания от Вас и хотели на собеседовании?
Поясню. В разных странах разные выходные дни, соответственно, при принятии задачи в разработку, необходимо хотя-бы поинтересоваться, о какой стране идёт речь?

Для практического решения этой задачи есть такой путь:
1. Создать таблицу КАЛЕНДАРЬ, автоматически заполняемую по событию,например, запросу начальника отдела кадров.
2. Должна быть таблица СТРАНЫ
3. Должна быть таблица отношений M-to-M КАЛЕНДАРЬ_СТРАНЫ, где и прописываются выходные и праздничные, прописываются автоматически, с ручной корректировкой на всякие Указы, постановления и т.п.
Это самый минимум.

После этого, Ваша задача надёжно и на все времена решается одним совсем небольшим SQL-запросом, который можно со спокойной совестью задвинуть в дальний чулан.
...
Рейтинг: 0 / 0
Вычисление числа рабочих дней между двумя датами
    #40049150
dmitryk1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
zeon11,

В принципе, если нужно массово высчитывать количество рабочих дней за случайные периоды, задачи кадрового учёта, то лучше делать это не вычислением списка, хоть это и проще, а одним выражением. Просто это быстрее. Хотя величину выигрыша стоило бы и протестировать.

По отношению к выходным в странах - на самом деле вариантов не так много. А про праздники тут речь не идёт и обрабатывать их получится только наполнением таблицы.

А вообще я согласен - задача по большей части бессмысленная и задаётся исключительно чтобы "проверить качество претендента". Потому и сюда выложил, вдруг кому-то зададут такую задачу. Чтобы люди не тратили время на бессмысленную ерунду.

zeon11Может этого понимания от Вас и хотели на собеседовании?
Кстати, про страну речи не было - всё однозначно, а вот мысли о том, чтобы сказать про невозможность, мне в голову не пришла, потому, что воспринималось мною как абстрактная математическая задачка. Так я её и решил.
...
Рейтинг: 0 / 0
17 сообщений из 17, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Вычисление числа рабочих дней между двумя датами
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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