Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Oracle Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
 Исключение выходные  [new]
царевич
Member

Откуда:
Сообщений: 115
Вывожу в запросе дату-время. Могу я в этом же запросе вывести дату-время на 3 дня больше, которая исключит суботу и воскресение?
спасибо
21 май 10, 15:45    [8815007]     Ответить | Цитировать Сообщить модератору
 Re: Исключение выходные  [new]
JaRo
Member

Откуда:
Сообщений: 1659
а по-русски? По любому ответ - можно. Теперь дело за вопросом.
21 май 10, 15:46    [8815017]     Ответить | Цитировать Сообщить модератору
 Re: Исключение выходные  [new]
царевич
Member

Откуда:
Сообщений: 115
JaRo,

в одном запросе хочу прибавить к дате 3 дня, но если внутрь этих трех дней попадают выходные то увеличить еще на количество выходных, т.е. 3+количество выходных.
выходные это СБ ВС
21 май 10, 15:52    [8815053]     Ответить | Цитировать Сообщить модератору
 Re: Исключение выходные  [new]
env
Member

Откуда: Россия, Москва
Сообщений: 6712
царевич,

0. По-тупому
case when to_number(to_char(dt,'d')) <=5 then dt+3 else dt+to_number(to_char(dt,'d'))-2 end 
1. Создать таблицу календарь и отметить в ней выходные.
21 май 10, 15:58    [8815112]     Ответить | Цитировать Сообщить модератору
 Re: Исключение выходные  [new]
Dmitry Ermolchik
Member

Откуда:
Сообщений: 21
царевич,

select decode (to_char(sysdate,'d'),6,sysdate+5,7,sysdate+4, sysdate+3) from dual
21 май 10, 16:10    [8815214]     Ответить | Цитировать Сообщить модератору
 Re: Исключение выходные  [new]
Dmitry Ermolchik
Member

Откуда:
Сообщений: 21
царевич,

Это при условии, что ваш Оракл начинает неделю с воскресенья
21 май 10, 16:11    [8815219]     Ответить | Цитировать Сообщить модератору
 Re: Исключение выходные  [new]
царевич
Member

Откуда:
Сообщений: 115
Почему то не работает. Подставил в оба предложенных варианта(они ниже) 30 мая, так как раз выходные впереди. В результат в обоих случаях 30.05.2010. А это ВОСКРЕСЕНИЕ:(
Есть идеи? К изменениям настроек оракла у меня доступпа нет. Хорошо б найти вариант без измненения настроек.
Спасибо

select decode (to_char(to_date('27.05.2010','dd.mm.yyyy'),'d'),6,to_date('27.05.2010','dd.mm.yyyy')+5,7,to_date('27.05.2010','dd.mm.yyyy')+4, to_date('27.05.2010','dd.mm.yyyy')+3) from dual

select case when to_number(to_char(to_date('27.05.2010','dd.mm.yyyy'),'d')) <=5 then to_date('27.05.2010','dd.mm.yyyy')+3 else to_date('27.05.2010','dd.mm.yyyy')+to_number(to_char(to_date('27.05.2010','dd.mm.yyyy'),'d'))-2 end from dual
1 июн 10, 14:03    [8869008]     Ответить | Цитировать Сообщить модератору
 Re: Исключение выходные  [new]
царевич
Member

Откуда:
Сообщений: 115
а резельтат должен быть 01.06.2010
1 июн 10, 14:12    [8869096]     Ответить | Цитировать Сообщить модератору
 Re: Исключение выходные  [new]
царевич
Member

Откуда:
Сообщений: 115
ой, ошибся, в оба предложенных решения податвил дату 27 мая
1 июн 10, 14:13    [8869105]     Ответить | Цитировать Сообщить модератору
 Re: Исключение выходные  [new]
Elic
Member

Откуда:
Сообщений: 29977
царевич
Почему то не работает to_char(<date>,'d')
RTFM NLS_TERRITORY (FAQ), STFF Вопрос про даты. Как получить ближайшее прошедшее воскресенье?
greatest(d, trunc(d+2, 'iw'))
1 июн 10, 14:22    [8869198]     Ответить | Цитировать Сообщить модератору
 Re: Исключение выходные  [new]
царевич
Member

Откуда:
Сообщений: 115
И все такие как мне прибавить 3 рабочих дня(с учетом выходных) одним запросом?
спасибо
1 июн 10, 16:45    [8870813]     Ответить | Цитировать Сообщить модератору
 Re: Исключение выходные  [new]
царевич
Member

Откуда:
Сообщений: 115
Умнее того что ниже ничего пока не придумал
Если у кого есть вариант покрасивее, подскажите, буду рад. спасибо

select decode (to_char(to_date('31.05.2010','dd.mm.yyyy'),'d'),
6,to_date('31.05.2010','dd.mm.yyyy')+5,
7,to_date('31.05.2010','dd.mm.yyyy')+4,
3,to_date('31.05.2010','dd.mm.yyyy')+5,
4,to_date('310.05.2010','dd.mm.yyyy')+5,
5,to_date('31.05.2010','dd.mm.yyyy')+5,
to_date('31.05.2010','dd.mm.yyyy')+3) from dual
1 июн 10, 18:02    [8872043]     Ответить | Цитировать Сообщить модератору
 Re: Исключение выходные  [new]
Andrey.L
Member

Откуда: Харьков
Сообщений: 1546
царевич,

Elic почти 4 часа назад привел красивое решение.
Покури еще раз это решение.
1 июн 10, 18:30    [8872271]     Ответить | Цитировать Сообщить модератору
 Re: Исключение выходные  [new]
царевич
Member

Откуда:
Сообщений: 115
Andrey.L,

я его к своей ситуации не смог применить
1 июн 10, 18:33    [8872287]     Ответить | Цитировать Сообщить модератору
 Re: Исключение выходные  [new]
-2-
Member

Откуда:
Сообщений: 15330
царевич
я его к своей ситуации не смог применить
С арифметикой проблемы?
with t as (
   select trunc(sysdate)+level d from dual connect by level<10
),
s as (
   select level n from dual connect by level < 10
),
r as (
   select n, d, greatest(d+n, trunc(d+n+2, 'iw')) dn
   from t cross join s
)
select *
from r pivot (
   max(to_char(dn,'dd day')) wn for n in (1,2,3,4,5,6,7,8,9)
) 
order by 1
;
1 июн 10, 19:07    [8872513]     Ответить | Цитировать Сообщить модератору
 Re: Исключение выходные  [new]
Elic
Member

Откуда:
Сообщений: 29977
Andrey.L
Elic почти 4 часа назад привел красивое решение.
Если бы автор яснее спрашивал...
with t as
( select trunc(sysdate+level) as wd from dual
    where trunc(sysdate+level) - trunc(sysdate+level, 'iw') < 5
    connect by level <= 20
), n as (select 3 as n from dual)
select to_char(wd, 'dd.mm.yyyy dy', 'nls_date_language=russian') "wd",
       to_char(
         trunc(wd, 'iw') + trunc((wd - trunc(wd, 'iw') + n) / 5) * 7 + mod((wd - trunc(wd, 'iw') + n), 5)
       , '"+ '||n||' =" dd.mm.yyyy dy', 'nls_date_language=russian'
       ) as "+ n = wd+n"
  from t, n;

wd            + n = wd+n
------------- -------------------
02.06.2010 ср + 3 = 07.06.2010 пн
03.06.2010 чт + 3 = 08.06.2010 вт
04.06.2010 пт + 3 = 09.06.2010 ср
07.06.2010 пн + 3 = 10.06.2010 чт
08.06.2010 вт + 3 = 11.06.2010 пт
09.06.2010 ср + 3 = 14.06.2010 пн
10.06.2010 чт + 3 = 15.06.2010 вт
11.06.2010 пт + 3 = 16.06.2010 ср
14.06.2010 пн + 3 = 17.06.2010 чт
15.06.2010 вт + 3 = 18.06.2010 пт
16.06.2010 ср + 3 = 21.06.2010 пн
17.06.2010 чт + 3 = 22.06.2010 вт
18.06.2010 пт + 3 = 23.06.2010 ср
21.06.2010 пн + 3 = 24.06.2010 чт
1 июн 10, 19:18    [8872570]     Ответить | Цитировать Сообщить модератору
Между сообщениями интервал более 1 года.
 Re: Исключение выходные  [new]
karbka
Member

Откуда:
Сообщений: 25
Всем привет.

Задача: исключить не только выходные, но и праздники, которые хранятся в отдельной таблице holiday. Пока на ум пришла идея через рекурсивный with, но вдруг кто элегантнее решение знает.

with dt as
(
   select to_date('07.12.2019', 'dd.mm.yyyy') as d from dual
),
nd as
( 
   select 13 as n from dual 
),
holiday(hd) as
(
   select to_date('25.12.2019', 'dd.mm.yyyy') from dual
   union all 
   select to_date('26.12.2019', 'dd.mm.yyyy') from dual
),
all_date(d, is_bd, bd_run) as 
(
  SELECT d,
         is_bd,
         is_bd as db_run
    FROM (
           select dt.d+1 as d, 
                  case
                     when h.hd is not null or (1 + trunc(d) - trunc(d, 'IW')) IN (6,7) then 
                        0
                     else
                        1
                  end as is_bd
             from dt,
                  holiday h
            where trunc(dt.d+1) = h.hd(+)
         )
   union all
  select d+1, 
         case
            when h.hd is not null or (1 + trunc(d+1) - trunc(d+1, 'IW')) IN (6,7) then 
               0
            else
               1
         end as is_bd,
         bd_run +
         case
            when h.hd is not null or (1 + trunc(d+1) - trunc(d+1, 'IW')) IN (6,7) then 
               0
            else
               1
         end as bd_run
    from all_date,
         holiday h,
         nd
   where trunc(d+1) = h.hd(+)
     and bd_run +
         case
            when h.hd is not null or (1 + trunc(d+1) - trunc(d+1, 'IW')) IN (6,7) then 
               0
            else
               1
         end <= n
)
select max(d) 
  from all_date
 where is_bd = 1;


Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production


Заранее спасибо.
7 дек 19, 21:17    [22034957]     Ответить | Цитировать Сообщить модератору
 Re: Исключение выходные  [new]
andreymx
Member

Откуда: Запорожье
Сообщений: 54381
karbka,

запиши в холодей еще и выходные и переносы к праздникам
а еще лучше сделай календарь - сколько часов в какой день по какому графику
8 дек 19, 09:37    [22035042]     Ответить | Цитировать Сообщить модератору
 Re: Исключение выходные  [new]
karbka
Member

Откуда:
Сообщений: 25
andreymx,

Holiday это только праздники, пользователь вносит через интерфейс. Календарь можно, да, но интересен вариант без него.
8 дек 19, 12:51    [22035093]     Ответить | Цитировать Сообщить модератору
 Re: Исключение выходные  [new]
andreymx
Member

Откуда: Запорожье
Сообщений: 54381
karbka
andreymx,

Holiday это только праздники, пользователь вносит через интерфейс. Календарь можно, да, но интересен вариант без него.
интересен, но в общем случае бесполезен
8 дек 19, 13:33    [22035101]     Ответить | Цитировать Сообщить модератору
 Re: Исключение выходные  [new]
karbka
Member

Откуда:
Сообщений: 25
andreymx,

На текущий момент имеется pl/sql функция, которая рассчитывает рабочий день, исключая только выходные аналогично решению от Elic. За UI отвечаю не я, на изменение этой части ресурсы никто не выделит, к сожалению. Поэтому думала выкрутиться на бекэнде, создав перегруженную функцию, которая бы исключала праздники тоже. Может, добавлю выходные в holiday с отдельным флагом. Подумаю.
8 дек 19, 13:57    [22035114]     Ответить | Цитировать Сообщить модератору
 Re: Исключение выходные  [new]
iOracleDev
Member

Откуда:
Сообщений: 1029
karbka,

Разный график работы в филиалах и часовые пояса? Работа с разными клиентами по разному графику?

Поинтересуйся, не будет ли задач расчета чего либо по рабочему времени, лучше сразу сделать производственный календарь, чем потом городить аццкий хардкод.
8 дек 19, 14:32    [22035130]     Ответить | Цитировать Сообщить модератору
 Re: Исключение выходные  [new]
karbka
Member

Откуда:
Сообщений: 25
iOracleDev,

Не, не связано с графиками работы, asset servicing: перенос дедлайнов на нужно количество рабочих дней вперед/назад.

PS. Почему так реализовали и почему до сих пор нет функции, учитывающей и bank holiday, не знаю. Есть отдельная функция, которая проверяет конкретный день праздник он или нет, но в вычислениях она не используется, только выходные исключаются, предполагая что в неделе всегда 5 рабочих дней.
8 дек 19, 15:09    [22035144]     Ответить | Цитировать Сообщить модератору
 Re: Исключение выходные  [new]
SY
Member

Откуда: Middlebury, CT USA
Сообщений: 10042
karbka
Календарь можно, да, но интересен вариант без него.


undefine workdays
with test_dates as (
                    select  date '2019-11-30' + level curr_date
                      from  dual
                      connect by level <= 14
                   ),
        holiday as (
                    select date '2019-12-25' hd from dual union all
                    select date '2019-12-26' hd from dual
                   ),
 not_a_holiday as (
                    select  trunc(sysdate,'yy') + level - 1 dt
                      from  dual
                      connect by trunc(sysdate,'yy') + level - 1 < date '2020-01-01'
                   minus
                    select  *
                      from  holiday
                  ),
      workdays as (
                   select  row_number() over(order by dt) rn,
                           dt workday
                     from  not_a_holiday
                     where dt - trunc(dt,'iw') <= 4
                  )
select  to_char(curr_date,'fmmm/dd/yyyy, Day') current_date,
        (
         select  to_char(workday,'fmmm/dd/yyyy, Day')
           from  workdays
           where connect_by_isleaf = 1
           start with workday = curr_date - least(0,curr_date - trunc(curr_date + 2,'iw'))
           connect by rn = prior rn + 1
                  and level <= &&workdays + 1
        )  current_date_plus_n_workdays
  from  test_dates
  order by curr_date
/
Enter value for workdays: 10
old  31:                   and level <= &&workdays + 1
new  31:                   and level <= 10 + 1

CURRENT_DATE          CURRENT_DATE_PLUS_N_WORKDAYS
--------------------- ----------------------------
12/1/2019, Sunday     12/16/2019, Monday
12/2/2019, Monday     12/16/2019, Monday
12/3/2019, Tuesday    12/17/2019, Tuesday
12/4/2019, Wednesday  12/18/2019, Wednesday
12/5/2019, Thursday   12/19/2019, Thursday
12/6/2019, Friday     12/20/2019, Friday
12/7/2019, Saturday   12/23/2019, Monday
12/8/2019, Sunday     12/23/2019, Monday
12/9/2019, Monday     12/23/2019, Monday
12/10/2019, Tuesday   12/24/2019, Tuesday
12/11/2019, Wednesday 12/27/2019, Friday
12/12/2019, Thursday  12/30/2019, Monday
12/13/2019, Friday    12/31/2019, Tuesday
12/14/2019, Saturday  12/31/2019, Tuesday

14 rows selected.

SQL> 


SY.

Сообщение было отредактировано: 8 дек 19, 20:16
8 дек 19, 19:51    [22035223]     Ответить | Цитировать Сообщить модератору
 Re: Исключение выходные  [new]
karbka
Member

Откуда:
Сообщений: 25
SY,

Компактно, спасибо! Единственное, в not_a_holiday старт, наверное, нужен от начальной даты curr_date, не начала текущего года и ограничивать чем-нибудь типа add_months(curr_date, 6)...

Сообщение было отредактировано: 8 дек 19, 20:46
8 дек 19, 20:37    [22035247]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
Все форумы / Oracle Ответить