У меня есть таблица, содержащая значения меток времени, и я хочу округлить каждое из этих значений до ближайшей секунды, но не могу заставить его работать должным образом.
Мои тестовые данные и подходы до сих пор:
with v_data as
(select to_timestamp('2012-12-10 10:49:30.00000000',
'YYYY-MM-DD HH24:mi:ss.FF8') base_val,
to_timestamp('2012-12-10 10:49:30',
'YYYY-MM-DD HH24:mi:ss') expected
from dual
union all
select to_timestamp('2012-12-10 10:49:30.46300000',
'YYYY-MM-DD HH24:mi:ss.FF8') base_val,
to_timestamp('2012-12-10 10:49:30',
'YYYY-MM-DD HH24:mi:ss') expected
from dual
union all
select to_timestamp('2012-12-10 10:49:30.50000000',
'YYYY-MM-DD HH24:mi:ss.FF8') base_val,
to_timestamp('2012-12-10 10:49:31',
'YYYY-MM-DD HH24:mi:ss') expected
from dual
union all
select to_timestamp('2012-12-10 10:49:30.56300000',
'YYYY-MM-DD HH24:mi:ss.FF8') base_val,
to_timestamp('2012-12-10 10:49:31',
'YYYY-MM-DD HH24:mi:ss') expected
from dual
union all
select to_timestamp('2012-12-10 10:49:30.99999999',
'YYYY-MM-DD HH24:mi:ss.FF8') base_val,
to_timestamp('2012-12-10 10:49:31',
'YYYY-MM-DD HH24:mi:ss') expected
from dual)
select v1.base_val,
v1.expected,
v1.base_val + (0.5 / 86400) solution_round,
cast(v1.base_val as date) as solution_cast,
extract(second from v1.base_val) - trunc(extract(second from v1.base_val)) fractional_seconds,
v1.base_val -
(extract(second from v1.base_val) - trunc(extract(second from v1.base_val))) / 86400 solution_add
from v_data v1
Все мои решения имеют недостаток:
- solution_round всегда округляет в большую сторону
- solution_cast работает до 11gR1, но в 11gR2 всегда округляет в меньшую сторону (причина: Oracle изменил поведение — теперь вместо округления выполняется усечение, см. https://forums.oracle.com/forums/thread.jspa?threadID=2242066)
- solution_add возвращает 10:49:29 вместо 10:49:31 для последних трех строк.
Я полагаю, что solution_add должен работать, и я только что сделал глупую ошибку :-)
ИЗМЕНИТЬ:
Решение Бена (см. ниже) работает для меня, но полагаться на to_char(timestamp, 'FF') кажется опасным - количество возвращаемых цифр зависит от определения временной метки.
Вместо этого я использую to_char(timestamp, 'FF3'), который надежно возвращает миллисекунды.
x + 0.5 / 86400 == x + (0.5 / 86400)
- person JJJ   schedule 10.12.2012x + 0.5 / 86400 ~= x + 0.0000058
). Разве это не должно быть( x + 0.5 ) / 86400
? - person JJJ   schedule 10.12.2012