Ответ 1
Вдохновленный комментарием @Frank, я провел несколько тестов и соответствующим образом адаптировал свой запрос. Это должно быть 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
.