私は毎晩01:00にリブートされるPostgreSQL 8.4のサーバーを持っています(尋ねないでください)。接続しているユーザーのリストを取得する必要があります(つまり、タイムスタンプは_u.login > u.logout
_):
_SELECT u.login, u.id, u.first_name
FROM pref_users u
WHERE u.login > u.logout and
u.login > now() - interval '24 hour'
ORDER BY u.login;
login | id | first_name
----------------------------+----------------+-------------
2012-03-14 09:27:33.41645 | OK171511218029 | Alice
2012-03-14 09:51:46.387244 | OK448670789462 | Bob
2012-03-14 09:52:36.738625 | OK5088512947 | Sergej
_
ただし、u.login > now()-interval '24 hour'
を比較すると、最後の01:00より前のユーザーも配信されます。これは特に悪いことです。朝に。
to_char()
で文字列アクロバットを行わずに最後の01:00以降のログインを取得するに効率的な方法はありますか?
@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
にキャストすると、どちらも同じlocal日付に変換され、timestamp [without time zone]
はローカルタイムゾーンにあると推定されます。も。したがって、対応するtimestamp with time zone
と比較すると、それらはすべて内部的に同じUTCタイムスタンプになります。タイムゾーン処理の詳細については、 関連する質問 をご覧ください。
5つのベスト。 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
よりわずかに高速です。
01:00以降の当日のタイムスタンプのみを取得する簡単な方法は、CURRENT_DATE + interval '1 hour'
したがって、クエリは次のようになります。
SELECT u.login, u.id, u.first_name
FROM pref_users u
WHERE u.login > u.logout AND
u.login > CURRENT_DATE + interval '1 hour'
ORDER BY u.login;
お役に立てば幸いです。
select * from termin where DATE(dateTimeField) >= CURRENT_DATE AND DATE(dateTimeField) < CURRENT_DATE + INTERVAL '1 DAY'
これは私にとってはうまくいきます-今日の日付を持つすべての行を選択します。
select * from termin where DATE(dateTimeField) = '2015-11-17'
これは私にとってはうまくいきます!
where
u.login > u.logout
and
date_trunc('day', u.login) = date_trunc('day', now())
and
date_trunc('hour', u.login) >= 1