Inspirado por el comentario de @Frank, realicé algunas pruebas y adapté mi consulta en consecuencia. Esto debería ser 1) correcto y 2) lo más rápido posible:
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;
Como no hay marcas de tiempo futuras en su tabla (supongo), no necesita un límite superior.date_trunc('day', now())
es casi lo mismo que now()::date
(o algunas otras alternativas detalladas a continuación), solo que devuelve timestamp
en lugar de una date
. Ambos dan como resultado una timestamp
de todos modos después de agregar un interval
.
Las siguientes expresiones funcionan de forma ligeramente diferente. Producen resultados sutilmente diferentes porque localtimestamp
devuelve el tipo de datos timestamp
mientras now()
devuelve timestamp with time zone
. Pero cuando se envía a date
, cualquiera de los dos se convierte al mismo local fecha y una timestamp [without time zone]
se supone que también está en la zona horaria local. Entonces, cuando se compara con la correspondiente timestamp with time zone
todos dan como resultado la misma marca de tiempo UTC internamente. Más detalles sobre el manejo de la zona horaria en esta pregunta relacionada.
Mejor de cinco. Probado con PostgreSQL 9.0. Repetido con 9.1.5:resultados consistentes con un margen de error del 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
es obviamente un poco más rápido que CURRENT_DATE
.