У меня есть столбец 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
Работает, как ожидается, но есть ли лучший способ?
EDIT :
Мне было интересно узнать производительность, поэтому я провел следующий тест с 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
.