Ispirato dal commento di @Frank, ho eseguito alcuni test e adattato la mia query di conseguenza. Questo dovrebbe essere 1) corretto e 2) il più veloce possibile:
SELECT u.login, u.id, u.first_name
FROM pref_users u
WHERE u.login > u.logout
AND u.login >= now()::date + interval '1h'
ORDER BY u.login;
Poiché non ci sono timestamp futuri nella tua tabella (presumo), non hai bisogno di un limite superiore.date_trunc('day', now())
è quasi uguale a now()::date
(o altre alternative descritte di seguito), solo che restituisce timestamp
invece di una date
. Entrambi danno come risultato un timestamp
comunque dopo aver aggiunto un interval
.
Le seguenti espressioni funzionano in modo leggermente diverso. Danno risultati leggermente diversi perché localtimestamp
restituisce il tipo di dati timestamp
mentre now()
restituisce timestamp with time zone
. Ma quando viene trasmesso a date
, entrambi vengono convertiti nello stesso locale data e un timestamp [without time zone]
si presume che sia anche nel fuso orario locale. Quindi, se confrontato con il corrispondente timestamp with time zone
risultano tutti nello stesso timestamp UTC internamente. Maggiori dettagli sulla gestione del fuso orario in questa domanda correlata.
Al meglio dei cinque. Testato con PostgreSQL 9.0. Ripetuto con 9.1.5:risultati coerenti con un margine di errore dell'1%.
SELECT localtimestamp::date + interval '1h' -- Total runtime: 351.688 ms
, current_date + interval '1h' -- Total runtime: 338.975 ms
, date_trunc('day', now()) + interval '1h' -- Total runtime: 333.032 ms
, now()::date + interval '1h' -- Total runtime: 278.269 ms
FROM generate_series (1, 100000)
now()::date
è ovviamente leggermente più veloce di CURRENT_DATE
.