Проще всего разбить это на 3 части:
- Первый неполный день (если есть)
- Последний неполный день (если есть)
- Промежуточные целые дни (если есть)
Первый неполный день - от позднего (время начала, 8:00) до раннего (last_date, 18:00 в первый день), поэтому мы вычитаемте, чтобы получить время для первого дня:
greatest ( least ( trunc(first_date)+18/24
, last_date
) - greatest( first_date
, trunc(first_date)+8/24
)
, 0) * 24 as last_day_hours
Внешняя функция greatest
гарантирует, что мы не получим отрицательное значение, например, если время начала после 6 часов вечера. * 10101
Еслипоследний день не совпадает с первым днем, тогда последний неполный день - с 8:00 до (конечное время) последнего дня:
case when trunc(last_date) != trunc(first_date)
then greatest ( least( last_date
, trunc(last_date)+18/24
)
- (trunc(last_date)+8/24)
, 0) * 24
else 0 end as last_day_hours
Все промежуточные дни (в часах):
greatest ( (trunc(last_date) - (trunc(first_date)+1))
, 0
) * 10 as intervening_days_in_hours
10 - количество часов с 8:00 до 18:00
Таким образом, сложение этих трех значений вместе дает общее количество часов за период, а умножение общей суммы на 3600 дает секунды:
(
(greatest ( least ( trunc(first_date)+18/24
, last_date
) - greatest( first_date
, trunc(first_date)+8/24
)
, 0) * 24)
+ case when trunc(last_date) != trunc(first_date)
then greatest ( least( last_date
, trunc(last_date)+18/24
)
- (trunc(last_date)+8/24)
, 0) * 24
else 0 end
+ (greatest ( (trunc(last_date) - (trunc(first_date)+1))
, 0
) * 10)
) * 3600 as total_seconds
Я не могу не чувствовать, что это должно быть легче, чем это, хотя!И, конечно, это не учитывает выходные.