Mam kolumnę DATE
, którą chcę zaokrąglić do następnej niższej 10-minutowej przerwy w zapytaniu (patrz przykład poniżej).Okrągła data do przedziału 10 minut
Udało mi się to zrobić obcinając sekundy, a następnie odejmując ostatnią cyfrę minut.
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
A oto wynik:
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
działa zgodnie z oczekiwaniami, ale tam jest lepszy sposób?
EDIT:
byłem ciekaw wyników, więc zrobiłem następujący test z 500.000 wierszy i (naprawdę nie) przypadkowych terminach. Zamierzam dodać wyniki jako komentarze do dostarczonych rozwiązań.
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;
Podejście to zajęło 03.24 s
.
Co o 'SELECT CASE WHEN to_char (date_col 'MI') między 0 a 10 THEN TO_DATE (to_char (date_col, 'YYYY') || '-' || TO_CHAR (date_col, 'MM') || '-' || TO_CHAR (date_col, 'DD') || '' || TO_CHAR (date_col, 'HH') || ': 00' "RRRR-MM-DD HH: MI") KONIEC "? –
@OMG Kucyki: Przepraszam, ale to zwraca pełną godzinę, gdy '0 <= MI <= 10', w przeciwnym razie' NULL'. –
Nie chciałeś zagracać z resztą KIEDY –