Ho una colonna DATE
che desidero arrotondare all'intervallo successivo inferiore di 10 minuti in una query (vedere l'esempio seguente).Intervallo di arrotondamento a intervalli di 10 minuti
Sono riuscito a farlo troncando i secondi e quindi sottraendo l'ultima cifra dei minuti.
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
Ed ecco il risultato:
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 2099/01/01 10: 00:00
funziona come previsto, ma c'è un modo migliore?
EDIT:
mi incuriosiva prestazioni, così ho fatto la seguente prova con 500.000 righe e (non proprio) date casuali. Ho intenzione di aggiungere i risultati come commenti alle soluzioni fornite.
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;
Questo approccio ha richiesto 03.24 s
.
Che dire 'SELECT CASE WHEN TO_CHAR (date_col, 'MI') tra 0 e 10 POI 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-GG HH: MI') END'? –
Ponticini @OMG: ci dispiace, ma restituisce l'ora completa quando '0 <= MI <= 10', altrimenti' NULL'. –
Non volevo ingombrare con il resto del QUARTO –