2009-12-26 8 views
37

Esiste un equivalente TIMESTAMPDIFF() per PostgreSQL?Differenza orario in ore per PostgreSQL

So che posso sottrarre due timestamp per ottenere un postgresql INTERVAL. Voglio solo la differenza tra i due timestamp in ore rappresentati da un INT.

posso fare questo in MySQL simili:

TIMESTAMPDIFF(HOUR, links.created, NOW()) 

devo solo la differenza tra due timestamp tra ore rappresentata come un intero.

soluzione funziona per me:

SELECT "links_link"."created", 
"links_link"."title", 
(EXTRACT(EPOCH FROM current_timestamp - "links_link"."created")/3600)::Integer AS "age" 
FROM "links_link" 

risposta

62

Le prime cose che appaiono a

EXTRACT(EPOCH FROM current_timestamp-somedate)/3600 

Potrebbe non essere abbastanza, ma sblocca la strada. Potrebbe essere più bello se fosse definita la divisione dell'intervallo per intervallo.

Modifica: se lo si desidera maggiore di zero, utilizzare abs o massimo (..., 0). Qualunque sia la tua intenzione.

Edit ++: il motivo per cui non ho usato age è che age con un singolo argomento, per citare la documentazione: Sottrarre da current_date (a mezzanotte). Significa che non si ottiene un'accurata "età" se non si esegue a mezzanotte. In questo momento è quasi 01:00 qui:

select age(current_timestamp); 
     age   
------------------ 
-00:52:40.826309 
(1 row) 
5

È possibile utilizzare il "estratto" o "la date_part" a intervalli così come timestamp, ma non credo che fa ciò che si vuole. Ad esempio, fornisce 3 per un intervallo di "2 giorni, 3 ore". Tuttavia, è possibile convertire un intervallo in un numero di secondi specificando 'epoch' come elemento temporale desiderato: extract(epoch from '2 days, 3 hours'::interval) restituisce 183600 (che quindi si divide per 3600 per convertire secondi in ore).

Quindi, mettendo tutto insieme, ottieni sostanzialmente la risposta di Michael: extract(epoch from timestamp1 - timestamp2)/3600. Dal momento che non sembra preoccuparsi che timestamp precede che, probabilmente, si vuole avvolgere che in abs:

SELECT abs(extract(epoch from timestamp1 - timestamp2)/3600) 
+0

Questo è davvero il più vicino. Eliminare tutti i decimali non dovrebbe essere un problema, anche se sono piuttosto rattristato dalla mancanza di una funzione incorporata per fare questo come MySQL. – TheLizardKing

+0

Non ci dovrebbero essere decimali, poiché eseguirà la divisione in interi. – araqnid

+0

araqnid, lo pensavo anche io, ma ho appena provato e in effetti produce un float. –

3

Questo potrebbe sembrare pazzo per un sacco di sviluppatori che amano approfittare delle funzioni di database,

Ma dopo aver esaustivo i problemi di pensiero, creazione e bugfix delle applicazioni per mysql e postgrsql con funzioni di confronto di php, sono giunto alla conclusione (per me), che il modo più semplice, che è il più semplice con meno mal di testa SQL, non è quello di approfittare di qualcuno di loro.

Perché? perché se si sta sviluppando in un linguaggio middleware come PHP, PHP ha tutte queste funzioni, e sono più facili da implementare nell'ode dell'applicazione confrontando gli interi. PostgreSQL timestamp NON è == unix timestamp e di MySQL unix timestamp non è PostgreSQL del o Oracoli timestamp .. diventa più difficile alla porta se si utilizza timestamp del database ..

quindi basta usare un intero, non è un timestamp, come il numero di secondi da gennaio 1 ° gennaio 1970 a mezzanotte. e non importa i timestamp del database. , e utilizzare gmdate() e memorizzare tutto come tempo gmt per evitare problemi di fuso orario.

se è necessario cercare, ordinare o confrontare il giorno da altri dati, o il mese o l'anno o il giorno della settimana, o qualsiasi cosa, nella propria applicazione, e tipo di dati INTEGER per time_day, time_hour, time_seconds. . o qualunque cosa tu voglia indicizzare per la ricerca, renderà i database più semplici e più portatili. è possibile utilizzare solo un campo, nella maggior parte dei casi: INTEGER time_created NOT NULL

(più campi nella riga del database sono l'unico lato negativo di questa soluzione che ho trovato e che non causa tanti mal di testa o tazze di caffè :)

Le funzioni di data di php sono eccezionali per confrontare le date, ma in mysql o postgresql, confrontando le date? nah .. usa il confronto intero in sql

mi rendo conto che può SEMERE più facile usare CURRENT_TIMESTAMP su una funzione di inserimento. HA! non farti ingannare.

Non puoi fare DELETE FROM SESSION_TABLE WHERE time-initialized < '2 days' se time-inizialized è un timestamp postgresql. ma si può fare:

DELETE FROM SESSION_TABLE WHERE time_initialized < '$yesterday'

Finché si imposta $ ieri a PHP come il numero intero di secondi dal 1970 che ieri era.

Questa è una gestione più semplice dei record di sessione rispetto al confronto di timestamp nelle istruzioni di selezione postgresql.

SELECT age(), SELECT extract() e asbtime sono mal di testa in uno di essi. questa è solo la mia opinione

si può fare addizione, sottrazione, <,>, il tutto con la data php oggetti

_peter_sysko U4EA Networks, Inc.

+2

Quindi, come si fa a garantire che solo le date valide vengano inserite nella "data intera"? Dove verificate se '2012-02-29' è valido o meno. Come fai a sapere se il tempo '02: 14' è valido per il 24 marzo? (Indica che non è valido ovunque a causa delle regole dell'ora legale). E l'eliminazione è abbastanza semplice: 'DELETE FROM SESSION_TABLE WHERE time-initialized

1

extract(hour from age(now(),links.created)) ti dà un conteggio pavimento arrotondato della differenza ora.

+3

Dopo tre anni ... Dubito. Inoltre: Cercando 'seleziona l'estratto (ora da '11 mons 30 giorni 23:00:00 ':: intervallo);' avrai solo' 23 'e non 11 mesi, 30 giorni e 23 ore espressi in ore (circa 8660) . –

3

PostgreSQL ottenere differenza secondi tra i timestamp

SELECT (
    (extract (epoch from (
     '2012-01-01 18:25:00'::timestamp - '2012-01-01 18:25:02'::timestamp 
         ) 
      ) 
    ) 
)::integer 

che stampa:

-2 

Perché i timestamp sono due secondi di distanza. Prendi il numero e dividi per 60 per ottenere i minuti, dividi per 60 di nuovo per ottenere ore.

17

campi arrivare dove un timestamp è maggiore di data in PostgreSQL:

SELECT * from yourtable 
WHERE your_timestamp_field > to_date('05 Dec 2000', 'DD Mon YYYY'); 

Sottrarre minuti dal timestamp in PostgreSQL:

SELECT * from yourtable 
WHERE your_timestamp_field > current_timestamp - interval '5 minutes' 

ore sottrarre da timestamp in PostgreSQL:

SELECT * from yourtable 
WHERE your_timestamp_field > current_timestamp - interval '5 hours' 
9

La risposta di Michael Krelin è vicina non è del tutto sicura, poiché può essere errata in rare situazioni. Il problema è che gli intervalli in PostgreSQL non hanno un contesto riguardo a cose come l'ora legale. Gli intervalli memorizzano le cose internamente come mesi, giorni e secondi. In questo caso, i mesi non rappresentano un problema poiché sottraendo due timestamp si usano solo giorni e secondi, ma i "giorni" possono essere un problema.

Se la sottrazione comporta cambi di ora legale, un giorno specifico può essere considerato rispettivamente 23 o 25 ore. L'intervallo ne terrà conto, il che è utile per conoscere la quantità di giorni passati in senso simbolico, ma fornirebbe un numero errato delle ore effettive passate. L'epoca dell'intervallo moltiplicherà tutti i giorni di 24 ore.

Ad esempio, se passa un giorno intero "breve" e un'ora aggiuntiva del giorno successivo, l'intervallo verrà registrato come un giorno e un'ora. Che convertito in epoca/3600 è di 25 ore. Ma in realtà 23 ore + 1 ora dovrebbe essere un totale di 24 ore.

Quindi il metodo più sicuro è:

(EXTRACT(EPOCH FROM current_timestamp) - EXTRACT(EPOCH FROM somedate))/3600 

Come Michael citato nel suo follow-up commento, avrete anche probabilmente desidera utilizzare piano() o rotondo() per ottenere il risultato come un valore intero .

Problemi correlati