Postgresは、次のように、date_trunc関数を使用してタイムスタンプを丸める(切り捨てる)ことができます。
date_trunc('hour', val)
date_trunc('minute', val)
タイムスタンプを最も近い5分の境界に切り捨てる方法を探しています。たとえば、14:26:57は14:25:00になります。これを行う簡単な方法は次のとおりです。
date_trunc('hour', val) + date_part('minute', val)::int / 5 * interval '5 min'
これはクエリのパフォーマンスが重要な部分なので、これが最速の解決策なのか、私が見落としているショートカット(Postgres 8.1以降と互換性がある)があるのか疑問に思っています。
より速い方法はないと思います。
そして、表現のパフォーマンスについて心配する必要はないと思います。
(SELECT、UPDATE、...)ステートメントの実行に関係する他のすべてのものは、おそらく日付/時刻の計算よりもはるかにコストがかかります(たとえば、行を取得するためのI/O)。
私も同じことを考えていました。私はこれを行う2つの代替方法を見つけましたが、あなたが提案した方法はより高速でした。
私は、より大きなテーブルの1つに対して非公式にベンチマークを行いました。クエリを最初の400万行に制限しました。私は2つのクエリを交互に使用して、dbキャッシングによる不当な利点を1つ与えないようにしました。
SELECT to_timestamp(
(EXTRACT(Epoch FROM ht.time) / EXTRACT(Epoch FROM interval '5 min'))::int
* EXTRACT(Epoch FROM interval '5 min')
) FROM huge_table AS ht LIMIT 4000000
(タイムゾーンを認識しないデータ型を使用した場合でも、これによりtimestamptz
が生成されることに注意してください)
結果
SELECT
date_trunc('hour', ht.time)
+ date_part('minute', ht.time)::int / 5 * interval '5 min'
FROM huge_table AS ht LIMIT 4000000
結果
システム
あなたのバージョンはより速いようです。しかし、私の特定のユースケースには十分な速度ではありません。時間を指定する必要がないという利点により、Epochバージョンがより用途が広くなり、クライアント側のコードでより簡単なパラメーター化が行われます。 2 hour
間隔だけでなく5 minute
バンプする必要のない間隔date_trunc
時間単位の引数がアップしています。最後に、この時間単位の引数を時間間隔の引数に変更したいと思います。
疑問に思っている人のための完全なクエリ(@DNSの質問に基づく):
注文があり、5minのスライスとshop_idでそれらをカウントしたい場合:
SELECT date_trunc('hour', created_at) + date_part('minute', created_at)::int / 5 * interval '5 min' AS minute
, shop_id, count(id) as orders_count
FROM orders
GROUP BY 1, shop_id
ORDER BY 1 ASC