2012-03-26 13 views
6

In SQL, ho una variabile DATE che desidero arrotondare alla prossima mezz'ora disponibile (ad es. Xx: 30). Si noti che questo non dovrebbe essere solo per la mezz'ora più vicina.Arrotondare il campo della data alla mezz'ora successiva in SQL

Ecco alcuni esempi:

Time     Expected outcome 
2012-03-26 11:25 AM 2012-03-26 11:30 AM 
2012-03-26 11:45 AM 2012-03-26 12:30 PM 

C'è un modo per fare questo in SQL?

risposta

5

Ha dato un +1 alla risposta di Justin per l'originalità.

Se si desidera una più pedante (o, forse più facilmente comprensibile o mantenute) aproach,

select case when to_number(to_char(sysdate,'mi')) > 30 
     then trunc(sysdate,'mi') + ((60 - to_number(to_char(sysdate,'mi')) +30)/1440) 
     else trunc(sysdate,'mi') + (30 - to_number(to_char(sysdate,'mi')))/1440 end 
from dual 

Sono solo giravo questo in là come questo potrebbe essere un approccio più flessibile, se si doveva fare qualcosa di simile contro altri numeri, come ad esempio 45 minuti dopo l'ora. Dovresti semplicemente sostituire i tre 30 con 45 e via.

Per prestazioni, tuttavia, per il tuo problema esatto - Justin è un vero vincitore.

10

E 'un po' contorto, ma qualcosa di simile

SELECT round((date_col - trunc(date_col)) * 48)/ 48 + 
     trunc(date_col) 
    FROM dual 

dovrebbe funzionare.

SQL> ed 
Wrote file afiedt.buf 

    1 select round((sysdate - trunc(sysdate)) * 48)/48 + trunc(sysdate), 
    2   sysdate 
    3* from dual 
SQL>/

ROUND((SYSDATE-TRUNC SYSDATE 
-------------------- -------------------- 
26-mar-2012 14:30:00 26-mar-2012 14:35:30 
  • TRUNC(date_col) tronca il tempo a mezzanotte.
  • date_col - trunc(date_col) restituisce la frazione di un giorno trascorso da mezzanotte.
  • Moltiplicando per 48 si indica il numero di incrementi di mezz'ora
  • arrotondamento che ti da più vicino mezz'ora
  • Poi dividendo per 48 ti dà una frazione di un giorno che può essere aggiunto di nuovo alla trunc(date_col)
+0

Questo aiuta, ma non è proprio quello che sto cercando. Arriva alla mezz'ora, ma ho bisogno della mezz'ora che termina in: 30. Quindi, nel tuo esempio sopra con '14: 35: 30', il risultato atteso sarebbe' 15: 30: 00'. – Paul

+0

E +1 per la soluzione intelligente. –

+0

Questa dovrebbe essere la risposta accettata! Per rispondere a Paul che ha chiesto il PROSSIMO, usa ceil invece di round. Per coloro che sono interessati al PREVIOUS, user floor invece di round. Modifica: Questo è spiegato nelle prossime risposte che non ho letto all'inizio, mi dispiace –

3

Ecco un piccolo aggiustamento alla risposta di Justin che penso che dà i risultati desiderati:

WITH thedate AS (SELECT trunc(SYSDATE)+6.5/48 thedate FROM dual) 
select round((thedate - trunc(thedate)) * 24 - 1/(24*3600))/24 + trunc(thedate)+1/48, 
      theDATE 
    from thedate; 

Fondamentalmente, questo arrotonda all'ora più vicina (dopo subtra cting un secondo per evitare di arrotondare quando sei esattamente sulla mezz'ora) quindi aggiunge una mezz'ora.

3

Il mio codice fa questa funzione ROUND utilizzando per arrotondare all'ora più vicina e poi l'aggiunta di mezz'ora

WITH thedate AS 
    (SELECT TO_DATE ('2012-03-26 11:20 AM', 'YYYY-MM-DD HH:MI AM') mydate 
     FROM DUAL) 
SELECT mydate, 
     TO_CHAR (ROUND (mydate, 'HH') + 1/48, 
       'YYYY-MM-DD HH:MI AM' 
       ) "Rounded Date" 
    FROM thedate; 

Speranza che aiuta

2

Per ottenere la mezz'ora successiva, modificare la soluzione di Justin Cave cambiando il ROUND a CEIL:

SELECT CEIL((date_col - trunc(date_col)) * 48)/ 48 + 
     trunc(date_col) 
    FROM dual 

ROUND va al più vicino (su o giù), CEIL sale al successivo a (sempre attivo).FLOOR passerebbe allo precedente (sempre verso il basso).

Per rispondere a punto di Michael Broughton su maintability:

48 è il numero di "ore e mezza" in un giorno. Per modificare il periodo, sostituire entrambe le istanze di:

60/x * 24 

dove x è il numero di minuti nel periodo che si desidera.

E.g. Ogni 10 minuti = (60/10) * 24 = 144.

Spero che questo aiuti!

0

semplificata (spero) ...

select 
    case 
    when to_number(to_char(sysdate,'mi')) <= 30 
     then trunc(sysdate,'hh24') + 30/1440 
     else trunc(sysdate,'hh24') + 1/24 
    end 
from dual; 
Problemi correlati