Вдохновленный комментарием @ Фрэнка, я провел несколько тестов и соответственно адаптировал свой запрос. Это должно быть 1) правильно и 2) максимально быстро:
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;
Поскольку в вашей таблице нет будущих временных отметок (я полагаю), вам не нужна верхняя граница.
date_trunc('day', now())
- почти то же самое, что и now()::date
(или некоторые другие альтернативы, подробно описанные ниже), только то, что он возвращает timestamp
вместо date
. Оба результата в любом случае timestamp
после добавления interval
.
Ниже выражения работают немного по-другому. Они дают немного разные результаты, потому что localtimestamp
возвращает тип данных timestamp
, а now()
возвращает timestamp with time zone
. Но при приведении к date
любой из них преобразуется в ту же локальную дату, и timestamp [without time zone]
также предполагается в местном часовом поясе. Таким образом, по сравнению с соответствующим timestamp with time zone
все они приводят к одной и той же временной метке UTC внутри. Подробнее об обработке часовых поясов в этом связанном вопросе .
Лучший из пяти. Протестировано с PostgreSQL 9.0. Повторяется с 9.1.5: согласованные результаты с погрешностью 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
явно немного быстрее, чем CURRENT_DATE
.