あなたの列created_at
はtimestamp without time zone
です 。
しかし、now()
timestamp with time zone
を返します 。式now() - '1 hour'::interval
timestamp [without time zone]
に強制されています 、2つの問題があります :
1。) あなたはこれを求めませんでしたが、表現は信頼できません。その結果は、クエリが実行されているセッションの現在のタイムゾーン設定によって異なります。詳細はこちら:
式を明確にするために、次を使用できます。
now() AT TIME ZONE 'Europe/London' -- your time zone here
または、(こちらのマニュアルをお読みください) :
LOCALTIMESTAMP -- explicitly take the local time
timestamptz
での作業を検討します 代わりに。
どちらも2番目の問題を解決しません:
2。)質問に答えます。 制約の除外は機能しません。 ドキュメントごと:
大胆な強調鉱山。
now()
CURRENT_TIMESTAMP
のPostgres実装です 。システムカタログでわかるように、それはSTABLE
だけです。 、IMMUTABLE
ではありません :
SELECT proname, provolatile FROM pg_proc WHERE proname = 'now';
proname | provolatile
--------+------------
now | s -- meaning: STABLE
ソリューション
1。) WHERE
に定数を指定することで、制限を克服できます。 条件(常に「不変」):
select count(*) from events
where created_at > '2015-05-25 15:49:20.037815'::timestamp; -- derived from your example
2。) または、不変関数を「偽造」することによって:
CREATE FUNCTION f_now_immutable()
RETURNS timestamp AS
$func$
SELECT now() AT TIME ZONE 'UTC' -- your time zone here
$func$ LANGUAGE sql IMMUTABLE;
そして:
select count(*) from events
where created_at > f_now_immutable() - interval '1 hour'
ただし、これをどのように使用するかに注意してください:while now()
STABLE
です (トランザクションの期間中は変更されません)、変更されます トランザクション間で変更されるため、プリペアドステートメント(パラメータ値を除く)やインデックスなど、噛み付く可能性のある場所でこれを使用しないように注意してください。
3。) または、一見冗長な定数WHERE
を追加することもできます パーティションの制約に一致する現在のクエリの句:
SELECT count(*)
FROM events
WHERE created_at > now() - '1 hour'::interval
AND created_at >= '2015-04-01 00:00:00'::timestamp
AND created_at <= '2015-04-30 23:59:59.999999'::timestamp;
now() - '1 hour'::interval
であることを確認してください 明らかに、適切なパーティションに分類されるか、結果が得られません。
余談ですが、CHECK
でこの式を使用したいと思います 制約とクエリ。取り扱いが簡単で同じことをします:
created_at >= '2015-04-01 0:0'::timestamp
AND created_at < '2015-05-01 0:0'::timestamp