Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 как раскидать интервал в часах на рабочие дни?  [new]
PavelVX
Member

Откуда: Новосибирск
Сообщений: 211
Всем добрый день!
Что-то не могу с наскоку решить следующую задачу: есть отрезок времени: стартовая дата + длина в часах.
Может кто-то подскажет, как рассчитать конечную дату(количество часов до нее) так, что бы длина в часах была только по рабочим часам?
Т.е. рабочий день пусть будет с 09:00 - 18:00, старт в 09:00, длительность 20 часов. В итоге я должен получить: 9+15+9+15+2=50ч.
Может кто сталкивался, кроме перебора как-то можно сделать это более элегантно.
20 апр 15, 12:16    [17538643]     Ответить | Цитировать Сообщить модератору
 Re: как раскидать интервал в часах на рабочие дни?  [new]
iap
Member

Откуда: Москва
Сообщений: 47083
PavelVX
Всем добрый день!
Что-то не могу с наскоку решить следующую задачу: есть отрезок времени: стартовая дата + длина в часах.
Может кто-то подскажет, как рассчитать конечную дату(количество часов до нее) так, что бы длина в часах была только по рабочим часам?
Т.е. рабочий день пусть будет с 09:00 - 18:00, старт в 09:00, длительность 20 часов. В итоге я должен получить: 9+15+9+15+2=50ч.
Может кто сталкивался, кроме перебора как-то можно сделать это более элегантно.
Стартовый день - 30 апреля.
Длительность - 100 часов.
Что должно получиться и откуда об этом должен знать сервер?
20 апр 15, 12:24    [17538710]     Ответить | Цитировать Сообщить модератору
 Re: как раскидать интервал в часах на рабочие дни?  [new]
LexusR
Member

Откуда: Novosibirsk
Сообщений: 1887
select 20/(18-9)*24+20%(18-9)
20 апр 15, 13:31    [17539197]     Ответить | Цитировать Сообщить модератору
 Re: как раскидать интервал в часах на рабочие дни?  [new]
LexusR
Member

Откуда: Novosibirsk
Сообщений: 1887
LexusR
select 20/(18-9)*24+20%(18-9)


вопрос с выходными и праздниками естественно остаётся за рамками постановки задачи )
20 апр 15, 13:32    [17539213]     Ответить | Цитировать Сообщить модератору
 Re: как раскидать интервал в часах на рабочие дни?  [new]
PavelVX
Member

Откуда: Новосибирск
Сообщений: 211
Про select 20/(18-9)*24+20%(18-9) - это просто круто!
С выходными и праздниками, правильный вопрос. В итоге создал табличку из 3х полей
1. дата
2. начало рабочего дня
3. конец рабочего дня

А на такое как раскидать N часов с определенного момента?
21 апр 15, 07:47    [17542133]     Ответить | Цитировать Сообщить модератору
 Re: как раскидать интервал в часах на рабочие дни?  [new]
aleks2
Guest
declare @t table(date datetime, beg datetime, [end] datetime);

insert @t
select '20150101', '20150101 09:00',  '20150101 18:00'
union all
select '20150102', '20150102 09:00',  '20150102 18:00'
union all
select '20150103', '20150103 09:00',  '20150103 18:00'
union all
select '20150105', '20150105 09:00',  '20150105 18:00'
union all
select '20150106', '20150106 09:00',  '20150106 18:00'

declare @N int, @d datetime;

set @N = 19;
set @d = '20150102';

;with
numbered as ( select *, row_number()over(order by date asc) as n from @t where date>=@d),
days as (
  select top(1) date
              , beg
              , [end] = case when dateadd(hh, @N, beg) > [end] then [end] else dateadd(hh, @N, beg) end
              , rest = @N - datediff(hh, beg, [end])
              , cast(1 as bigint) as n 
    from numbered where n = 1 
  union all
  select t.date
       , t.beg
       , [end] = case when dateadd(hh, d.rest, t.beg) > t.[end] then t.[end] else dateadd(hh, d.rest, t.beg) end
       , rest = d.rest - datediff(hh, t.beg, t.[end])
       , t.n 
    from numbered t inner join days d on t.n = d.n+1
    where d.rest > 0
)
select * from days;
21 апр 15, 10:36    [17542732]     Ответить | Цитировать Сообщить модератору
 Re: как раскидать интервал в часах на рабочие дни?  [new]
VGalamakh
Member

Откуда: Киев (Альба)
Сообщений: 66
Как вариант

declare @datestart datetime = getdate(),
		@dateend datetime,		
		@work_hours int = 20

declare @t table
(
 dt datetime,
 work_begin int,
 dinner_begin int,
 dinner_end int,
 work_end int
 )
 
 declare @t1 table
(
 dt datetime,
 work_begin int,
 dinner_begin int,
 dinner_end int,
 work_end int,
 work_minute_first_period int,
 work_minute_second_period int,
 work_minute int
 )
 
 insert @t
 Select '2015/04/20',9,13,14,18
 union all
 Select '2015/04/21',9,13,14,18
 union all
 Select '2015/04/22',9,13,14,18
 union all
 Select '2015/04/23',9,13,14,18
 union all
 Select '2015/04/24',9,13,14,18
 union all
 Select '2015/04/25',0,0,0,0
 union all
 Select '2015/04/26',0,0,0,0
 union all
 Select '2015/04/27',9,13,14,18
 union all
 Select '2015/04/28',9,13,14,18
 
 insert @t1
 Select dt, work_begin, dinner_begin, dinner_end, work_end,
 case 
	when @datestart < dateadd(hour,work_begin,dt) then DATEDIFF(minute,dateadd(hour,work_begin,dt),dateadd(hour,dinner_begin,dt))
	when @datestart between dateadd(hour,work_begin,dt) and dateadd(hour,dinner_begin,dt) then DATEDIFF(minute,@datestart,dateadd(hour,dinner_begin,dt))
	else 0 end,
 case 
	when @datestart < dateadd(hour,dinner_end,dt) then DATEDIFF(minute,dateadd(hour,dinner_end,dt),dateadd(hour,work_end,dt))
	when @datestart between dateadd(hour,dinner_end,dt) and dateadd(hour,work_end,dt) then DATEDIFF(minute,@datestart,dateadd(hour,work_end,dt))
	else 0 end,
	0	
  from @t
  where dt>=CAST(@datestart as DATE)
 
 update a
 set work_minute=(Select SUM(work_minute_first_period+work_minute_second_period) from  @t1 b where a.dt>=b.dt)
 from @t1 a
 
 Select top 1 @dateend = dt from @t1 
 where work_minute>=@work_hours*60
 order by 1
 
 delete from @t1  
 where dt>@dateend
 
 Select 
 case when work_minute-(work_minute_second_period+work_minute_first_period) <=@work_hours*60 then DATEADD(minute,@work_hours*60 - (work_minute-(work_minute_second_period+work_minute_first_period)),dateadd(hour,work_begin,dt))
      when work_minute-work_minute_second_period<=@work_hours*60 then DATEADD(minute,@work_hours*60 - (work_minute-work_minute_second_period),dateadd(hour,dinner_end,dt))
 end
 from @t1 
 where dt=@dateend
21 апр 15, 10:53    [17542798]     Ответить | Цитировать Сообщить модератору
 Re: как раскидать интервал в часах на рабочие дни?  [new]
PavelVX
Member

Откуда: Новосибирск
Сообщений: 211
Спасибо за варианты. Я понял, что ничего не понимаю в SQL.
6 май 15, 07:30    [17605234]     Ответить | Цитировать Сообщить модератору
 Re: как раскидать интервал в часах на рабочие дни?  [new]
PavelVX
Member

Откуда: Новосибирск
Сообщений: 211
VGalamakh, aleks2
Это супер! За час разобрался, что же вы предлагали и остановился на варианте VGalamakh.
Это просто супер, просуммировать интервалы вперед я сам не догадался :(
Еще раз всем большое спасибо!
6 май 15, 08:22    [17605319]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить