Pull to refresh
0
0
Send message
Я лишь взял Ваше решение по вашей же ссылке. Почему у вас там оказался неверный набор выходных и праздников — спросите у себя.
Так что тут неизвестно кто первый не озаботился. :)

Ваше решение мне нравится лаконичностью, понятностью и чистотой.

Решение от OrmEugensson более мудреное и сложное, но и гораздо более производительное, чем наши с вами.

С чего вы взяли что ваша задача (подсчет общей суммы массива), более актуальнее моей (подсчет для конкретной заявки)?

Мне такие кейсы встречаются чаще. Как-то даже не пришло в голову иначе протестировать.
Интереса ради я написал запрос, который работает быстрее ваших ещё на (десятичный) порядок, избавившись от суммы по интервалам, и получив скорость работы линейно зависящую только от количества интервалов. Видимо придётся добавить в разбор задачи слова про производительность.

Вот на это интересно посмотреть, буду ждать.
А ваше решение работает на 10% медленнее чем моё и дело там не в постгресе:)

Тут можно сравнить более объективно:
Ваше решение
Мое

И у Вас ошибка где-то, не сходится сумма…
Пожалуй что именно его решение (ссылка) показалось мне самым интересным по компактности и выразительности.

Но не по производительности.
Его решение работает в 10 раз медленнее, чем, например, мое.

Без претензий на лавры, PostgreSQL вообще не мой родной.
Да, действительно упустил один момент.
Протер глаза
with 
periods(id, start_time, stop_time) as ( values
  (1, '2019-03-29 07:00:00'::timestamp, '2019-04-08 14:00:00'::timestamp),
  (2, '2019-04-10 07:00:00'::timestamp, '2019-04-10 20:00:00'::timestamp),
  (3, '2019-04-11 12:00:00'::timestamp, '2019-04-12 16:07:12'::timestamp),
  (4, '2018-12-28 12:00:00'::timestamp, '2019-01-16 16:00:00'::timestamp)
),
holidays(date_key) as ( values 
  ('2018-01-01'::date), ('2018-01-02'::date), ('2018-01-03'::date), ('2018-01-04'::date), ('2018-01-05'::date), ('2018-01-08'::date), ('2018-02-23'::date), ('2018-03-08'::date), ('2018-03-09'::date), ('2018-04-30'::date), ('2018-05-01'::date), ('2018-05-02'::date), ('2018-05-09'::date), ('2018-06-11'::date), ('2018-06-12'::date), ('2018-11-05'::date), ('2018-12-31'::date), 
  ('2019-01-01'::date), ('2019-01-02'::date), ('2019-01-03'::date), ('2019-01-04'::date), ('2019-01-07'::date), ('2019-01-08'::date), ('2019-03-08'::date), ('2019-05-01'::date), ('2019-05-02'::date), ('2019-05-03'::date), ('2019-05-09'::date), ('2019-05-10'::date), ('2019-06-12'::date), ('2019-11-04'::date)
),
work_holidays(date_key) as ( values 
  ('2018-04-28'::date), ('2018-06-09'::date), ('2018-12-29'::date)
)
select p.id, p.start_time, p.stop_time,  
       -- hours from start_time
       case 
         when start_time::date = stop_time::date or start_time::date = min(h.time_key) then '00:00:00'::interval      
         else '19:00:00'::time - greatest(least(start_time::time, '19:00:00'::time), '10:00:00'::time)      
       end +
       -- hours from stop_time
       case           
         when stop_time::date = max(h.time_key)  then '00:00:00'::interval
         when stop_time::date = start_time::date then greatest(least('19:00:00'::time, stop_time::time) - greatest('10:00:00'::time, start_time::time), '00:00:00'::interval)      
         else greatest(least(stop_time::time, '19:00:00'::time), '10:00:00'::time) - '10:00:00'::time
       end +
       -- 
       (
          greatest(p.stop_time::date - p.start_time::date - 1, 0) 
        - sum(case when h.time_key > p.start_time::date and h.time_key < p.stop_time::date then 1 else 0 end)
       )*'09:00:00'::interval as answer
from periods p
left outer join
(   -- all free days
  select time_key::date
  from generate_series(
    (select min(start_time)::date from periods), 
    (select max(stop_time)::date from periods), 
    interval '1 day'
  ) as time_key
  where to_char(time_key, 'D') in ('1', '7')
  union 
  select date_key
  from holidays
  except
  select date_key
  from work_holidays
) h   
on h.time_key between p.start_time::date and p.stop_time::date
group by p.id, p.start_time, p.stop_time

Так вижу
with 
periods(id, start_time, stop_time) as ( values
  (1, '2019-03-29 07:00:00'::timestamp, '2019-04-08 14:00:00'::timestamp),
  (2, '2019-04-10 07:00:00'::timestamp, '2019-04-10 20:00:00'::timestamp),
  (3, '2019-04-11 12:00:00'::timestamp, '2019-04-12 16:07:12'::timestamp),
  (4, '2018-12-28 12:00:00'::timestamp, '2019-01-16 16:00:00'::timestamp)	    
),
holidays(date_key) as ( values 
  ('2018-01-01'::date), ('2018-01-02'::date), ('2018-01-03'::date), 
  ('2018-01-04'::date), ('2018-01-05'::date), ('2018-01-08'::date), 
  ('2018-02-23'::date), ('2018-03-08'::date), ('2018-03-09'::date), 
  ('2018-04-30'::date), ('2018-05-01'::date), ('2018-05-02'::date), 
  ('2018-05-09'::date), ('2018-06-11'::date), ('2018-06-12'::date), 
  ('2018-11-05'::date), ('2018-12-31'::date), 
  ('2019-01-01'::date), ('2019-01-02'::date), ('2019-01-03'::date), 
  ('2019-01-04'::date), ('2019-01-07'::date), ('2019-01-08'::date), 
  ('2019-03-08'::date), ('2019-05-01'::date), ('2019-05-02'::date), 
  ('2019-05-03'::date), ('2019-05-09'::date), ('2019-05-10'::date), 
  ('2019-06-12'::date), ('2019-11-04'::date)
),
work_holidays(date_key) as ( values 
  ('2018-04-28'::date), ('2018-06-09'::date), ('2018-12-29'::date)
)
select p.id, p.start_time, p.stop_time,        
       -- hours from start_time
       case 
         when start_time::date = min(h.time_key)  then '00:00:00'::interval
         when start_time::date = stop_time::date  then '00:00:00'::interval
	 when start_time::time > '19:00:00'::time then '00:00:00'::interval
	 when start_time::time < '10:00:00'::time then '09:00:00'::interval
	 else '19:00:00'::time - start_time::time
       end +
       -- hours from stop_time
       case 	        
         when stop_time::date = max(h.time_key)  then '00:00:00'::interval
	 when stop_time::date = start_time::date then least('19:00:00'::time,  stop_time::time) - greatest('10:00:00'::time, start_time::time)
	 when stop_time::time > '19:00:00'::time then '09:00:00'::interval
         when stop_time::time < '10:00:00'::time then '00:00:00'::interval
	 else stop_time::time - '10:00:00'::time
       end +
        -- 
       (
         -- count all days
	 greatest(p.stop_time::date - p.start_time::date - 1, 0) 
         -- count holidays 
	 -sum(case when h.time_key > p.start_time::date and h.time_key < p.stop_time::date then 1 else 0 end)
       )*'09:00:00'::interval as answer
from periods p
left outer join
(
  select time_key::date
  from generate_series(
    (select min(start_time)::date from periods), 
    (select max(stop_time)::date from periods), 
    interval '1 day'
  ) as time_key
  where to_char(time_key, 'D') in ('1', '7')
  union 
  select date_key
  from holidays
  except
  select date_key
  from work_holidays
) h	 
on h.time_key between p.start_time::date and p.stop_time::date
group by p.id, p.start_time, p.stop_time
order by p.id


Хотелось бы увидеть фото готовых изделий, напечатанных с помощью этого принтера. Или максимальная высота 5 мм?
Визуальное решение, так сказать, без формул.
Можно обратить внимание, что стартовое положение спортсменов во втором забеге соответствует финишному положению первого забега.
Т.е. второй забег — это зеркальное отражение первого.
Следовательно, если отмотать «пленку», спортсмены во втором забеге финишируют одновременно.
Один массив (возможно, и очередь) можно рекурсивно отсортировать вообще без дополнительных/временных переменных.
Почему бы не сделать проще:

Слить две очереди в одну.
Отсортировать с учетом требований.

Information

Rating
Does not participate
Registered
Activity