Гость
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Вычисление числа рабочих дней между двумя датами / 17 сообщений из 17, страница 1 из 1
26.10.2004, 14:09
    #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
26.10.2004, 14:25
    #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
26.10.2004, 14:27
    #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
26.10.2004, 14:42
    #32755025
Leonid_B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вычисление числа рабочих дней между двумя датами
Обсуждалось и не раз. STFW , в то числе у Кайта.
Приведенные запросы не учитывают праздничные дни.
...
Рейтинг: 0 / 0
26.10.2004, 14:49
    #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
26.10.2004, 15:06
    #32755109
AlexKulikov
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вычисление числа рабочих дней между двумя датами
Leonid_BОбсуждалось и не раз. STFW , в то числе у Кайта.
Приведенные запросы не учитывают праздничные дни.

Само собой не учитываются праздники, а так же переносы, которые установлены законодательством на текущий год, но если это учитывать, то надо еще написать интерфейс для ведения праздников и переносов, купить лицензию на консультант или гарант, в общем это уже не "простое SQL предложение" суть как я понял, просто посчитать количество понедельников- пятницев в период между датами. единственно смущает ограничение по операторам, может это лаба, и нужно обойтись перечисленным набором операторов.... а на счет праздников - в связи с переносом рабочим может назначиться суббота или воскресенье, а в постановке четко сказано не считать сбт и вск, следовательно к праздникам привязки нет :)
...
Рейтинг: 0 / 0
26.10.2004, 16:32
    #32755349
misha_22
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вычисление числа рабочих дней между двумя датами
Спасибо.
Да, верно, надо подсчитать только количествово дней с понедельника по пятницу.
...
Рейтинг: 0 / 0
13.12.2004, 17:12
    #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
13.12.2004, 17:52
    #32825647
Elic
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вычисление числа рабочих дней между двумя датами
Факир, замени dba_objects на любой набор данных, имеющий достаточное количество строк. В первом приближении - на all_objects.
См. также select натуральный ряд
...
Рейтинг: 0 / 0
13.12.2004, 18:23
    #32825686
SY
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
14.12.2004, 13:37
    #32826604
Вычисление числа рабочих дней между двумя датами
Эс Вай мой кумир!
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
26.02.2021, 09:13
    #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
26.02.2021, 09:43
    #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
26.02.2021, 10:19
    #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
26.02.2021, 13:52
    #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
26.02.2021, 18:20
    #40049084
zeon11
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вычисление числа рабочих дней между двумя датами
dmitryk1,
Эта задача не имеет практического универсального решения средствами SQL. Может этого понимания от Вас и хотели на собеседовании?
Поясню. В разных странах разные выходные дни, соответственно, при принятии задачи в разработку, необходимо хотя-бы поинтересоваться, о какой стране идёт речь?

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

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

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

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

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

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


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