5

Rails データベース (Postgres) の purchases テーブルにクエリを実行しようとしていますが、時間範囲についてクエリを実行したいと考えています。

たとえば、すべての日付で午後 2 時から午後 3 時までに行われた購入の数を知りたいです。

この表にはcreated_at列がありますが、特定の日付も検索しないとこれを達成する方法がわかりません。

私はもう試した:

Purchases.where("created_at BETWEEN ? and ?", Time.now - 1.hour, Time.now)

しかし、これは最終的にそれらの時間で今日の日付を検索するだけです。

4

2 に答える 2

6

PostgreSQL の date_part/extract 関数を使用して、created_at から時間の部分だけを抽出する必要があります。

SELECT EXTRACT(HOUR FROM TIMESTAMP '2001-02-16 20:38:40');
Result: 20

たとえば、次のようなものです。

Purchases.where(["EXTRACT(HOUR FROM created_at) BETWEEN ? AND ?", 13, 14])
于 2013-10-14T20:02:04.053 に答える
4

への単純なキャストを使用しtimeます。

Purchases.where("created_at::time >= ?
             AND created_at::time <  ?", Time.now - 1.hour, Time.now)

このようにして、任意の時間に対して簡単にテストできます。

検討:

  • 含める/除外する境界線。一般的な方法は、下の境界線を含めて上の境界線を除外することです。BETWEEN 両方を含みます。

  • 正確なデータ型 (timestampまたはtimestamp with time zone) と、それがローカル タイム ゾーンとどのように相互作用するか:

索引

これらのクエリを頻繁に実行し、それらを高速に実行する必要があり、テーブルがそれほど小さくない場合は、パフォーマンスのために関数インデックスを作成する必要があります。

CREATE INDEX tbl_created_at_time_idx ON tbl (cast(created_at AS time));

Postgres 構文のショートカットの代わりに、標準の SQL 構文cast()::を使用しました。これはインデックスに必要です。

timestamp [without time zone]インデックスにはキャストがIMMUTABLE必要なため、このインデックスは aで機能します。timestamp with time zoneしかし、同じ理由で、 では機能しません。これは修正できますが、必要なものを正確に定義する必要があります。コンストラクトを使用してAT TIME ZONE、時間を抽出するタイム ゾーンを定義します。たとえば、UTC 時間に対して測定するには、次のようにします。

CREATE INDEX tbl_created_at_time_idx2
ON tbl(cast(created_at AT TIME ZONE 'UTC' AS time));

年を無視した日付を扱う同様の質問:

于 2013-10-14T20:45:58.770 に答える