Q: В Oracle есть функция, которая вычисляет разницу между двумя датами?
Просто вычтите одно выражение даты из другого, чтобы получить разницу, выраженную в количестве дней. Целая часть - это число целых дней, дробная часть - это доля дня. Простая арифметика после этого умножьте на 24, чтобы получить часы.
Q: Если нет, то есть ли способ показать разницу между двумя датами в часах и минутах?
Это просто вопрос выражения продолжительности в виде целых часов и оставшихся минут.
Мы можем перейти к «старой школе», чтобы получить длительности в формате ччч: ми, используя комбинацию простых встроенных функций:
SELECT decode(sign(t.maxst),-1,'-','')||to_char(floor(abs(t.maxst)/60))||
decode(t.maxst,null,'',':')||to_char(mod(abs(t.maxst),60),'FM00')
as MaximumScheduleTime
, decode(sign(t.minst),-1,'-','')||to_char(floor(abs(t.minst)/60))||
decode(t.minst,null,'',':')||to_char(mod(abs(t.minst),60),'FM00')
as MinimumScheduleTime
, decode(sign(t.avgst),-1,'-','')||to_char(floor(abs(t.avgst)/60))
decode(t.avgst,null,'',':')||to_char(mod(abs(t.avgst),60),'FM00')
as AverageScheduleTime
FROM (
SELECT round(max((EndDate - StartDate) *1440),0) as maxst
, round(min((EndDate - StartDate) *1440),0) as minst
, round(avg((EndDate - StartDate) *1440),0) as avgst
FROM table1
) t
Да, это ужасно, но довольно быстро. Вот более простой случай, который лучше показывает, что происходит:
select dur as "minutes"
, abs(dur) as "unsigned_minutes"
, floor(abs(dur)/60) as "unsigned_whole_hours"
, to_char(floor(abs(dur)/60)) as "hhhh"
, mod(abs(dur),60) as "unsigned_remainder_minutes"
, to_char(mod(abs(dur),60),'FM00') as "mi"
, decode(sign(dur),-1,'-','') as "leading_sign"
, decode(dur,null,'',':') as "colon_separator"
from (select round(( date_expr1 - date_expr2 )*24*60,0) as dur
from ...
)
(заменить date_expr1
и date_expr2
на выражения даты)
распакуем это
date_expr1 - date_expr2
возвращает разницу в количестве дней
- умножить на 1440 (24 * 60), чтобы получить длительность в минутах
round
(или floor
) для преобразования дробных минут в целые минуты
- делим на 60, целое число - часы, остаток - минуты
abs
функция для получения абсолютного значения (изменение отрицательного значения на положительное)
to_char
модель формата FM00
дают две цифры (начальные нули)
- используйте функцию
decode
для форматирования отрицательного знака и двоеточия (при необходимости)
Оператор SQL можно сделать менее уродливым с помощью функции PL / SQL, которая принимает два аргумента DATE длительность в (дробных) днях и возвращает отформатированный hhhh: mi
( непроверенных )
create function hhhhmi(an_dur in number)
return varchar2 deterministic
is
begin
if an_dur is null then
return null;
end if;
return decode(sign(an_dur),-1,'-','')
|| to_char(floor(abs(an_dur)*24))
||':'||to_char(mod((abs(an_dur)*1440),60),'FM00');
end;
С определенной функцией:
SELECT hhhhmi(max(EndDate - StartDate)) as MaximumScheduleTime
, hhhhmi(min(EndDate - StartDate)) as MinimumScheduleTime
, hhhhmi(avg(EndDate - StartDate)) as AverageScheduleTime
FROM table1