У меня есть столбец DATE
, который я хочу округлить до следующего 10-минутного интервала в запросе (см. пример ниже).
Мне удалось сделать это, усекав секунды, а затем вычитая последнюю цифру минут.
WITH test_data AS (
SELECT TO_DATE('2010-01-01 10:00:00', 'YYYY-MM-DD HH24:MI:SS') d FROM dual
UNION SELECT TO_DATE('2010-01-01 10:05:00', 'YYYY-MM-DD HH24:MI:SS') d FROM dual
UNION SELECT TO_DATE('2010-01-01 10:09:59', 'YYYY-MM-DD HH24:MI:SS') d FROM dual
UNION SELECT TO_DATE('2010-01-01 10:10:00', 'YYYY-MM-DD HH24:MI:SS') d FROM dual
UNION SELECT TO_DATE('2099-01-01 10:00:33', 'YYYY-MM-DD HH24:MI:SS') d FROM dual
)
-- #end of test-data
SELECT
d, TRUNC(d, 'MI') - MOD(TO_CHAR(d, 'MI'), 10) / (24 * 60)
FROM test_data
И вот результат:
01.01.2010 10: 00:00 01.01.2010 10: 00:00
01.01.2010 10: 05:00 01.01.2010 10: 00:00
01.01.2010 10: 09:59 01.01.2010 10: 00:00
01.01.2010 10: 10:00 01.01.2010 10: 10:00
01.01.2099 10: 00:33 01.01.2099 10: 00:00
Работает так, как ожидалось, но есть ли лучший способ?
ИЗМЕНИТЬ
Мне было интересно узнать о производительности, поэтому я провел следующий тест с 500 000 строк и (не совсем) случайными датами. Я собираюсь добавить результаты в виде комментариев к предоставленным решениям.
DECLARE
t TIMESTAMP := SYSTIMESTAMP;
BEGIN
FOR i IN (
WITH test_data AS (
SELECT SYSDATE + ROWNUM / 5000 d FROM dual
CONNECT BY ROWNUM <= 500000
)
SELECT TRUNC(d, 'MI') - MOD(TO_CHAR(d, 'MI'), 10) / (24 * 60)
FROM test_data
)
LOOP
NULL;
END LOOP;
dbms_output.put_line( SYSTIMESTAMP - t );
END;
Этот подход занял 03.24 s
.