Tengo una columna DATE
que quiero redondear al siguiente intervalo inferior de 10 minutos en una consulta (ver ejemplo a continuación).Fecha de la ronda a intervalo de 10 minutos
Logré hacerlo truncando los segundos y luego restando el último dígito de minutos.
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
Y aquí está el resultado:
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
funciona como se espera, pero hay una manera mejor?
EDITAR:
tenía curiosidad sobre el rendimiento, así que lo hice la siguiente prueba con 500.000 filas y (no realmente) fechas al azar. Voy a agregar los resultados como comentarios a las soluciones proporcionadas.
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;
Este enfoque tomó 03.24 s
.
¿Qué hay de 'SELECT CASE CUANDO TO_CHAR (date_col, 'MI') entre 0 y 10, entonces TO_DATE (TO_CHAR (date_col, 'YYYY') || '-' || TO_CHAR (date_col, 'MM') || '-' || TO_CHAR (date_col, 'DD') || '' || TO_CHAR (date_col, 'HH') || ': 00' , 'AAAA-MM-DD HH: MI') END'? –
@OMG Ponies: Lo siento, pero eso devuelve la hora completa cuando '0 <= MI <= 10', de lo contrario' NULL'. –
No quería saturar el resto de CUANDO –