Ihre Spalte created_at
ist timestamp without time zone
.
Aber now()
gibt timestamp with time zone
zurück . Der Ausdruck now() - '1 hour'::interval
wird auf timestamp [without time zone]
gezwungen , die zwei Probleme mit sich bringt :
1.) Sie haben nicht danach gefragt, aber der Ausdruck ist unzuverlässig. Das Ergebnis hängt von der aktuellen Zeitzoneneinstellung der Sitzung ab, in der die Abfrage ausgeführt wird. Details hier:
Um den Ausdruck klarer zu machen, könnten Sie verwenden:
now() AT TIME ZONE 'Europe/London' -- your time zone here
Oder einfach (hier das Handbuch lesen) :
LOCALTIMESTAMP -- explicitly take the local time
Ich würde in Betracht ziehen, mit timestamptz
zu arbeiten stattdessen.
Keines von beiden löst Ihr zweites Problem:
2.) Antwort auf Ihre Frage. Der Einschränkungsausschluss funktioniert nicht. Pro Dokumentation:
Fettdruck von mir.
now()
ist die Postgres-Implementierung von CURRENT_TIMESTAMP
. Wie Sie im Systemkatalog sehen können, ist es nur STABLE
, nicht IMMUTABLE
:
SELECT proname, provolatile FROM pg_proc WHERE proname = 'now';
proname | provolatile
--------+------------
now | s -- meaning: STABLE
Lösungen
1.) Sie können die Einschränkung überwinden, indem Sie eine Konstante im WHERE
angeben Bedingung (die immer "unveränderlich" ist):
select count(*) from events
where created_at > '2015-05-25 15:49:20.037815'::timestamp; -- derived from your example
2.) Oder durch "Fake" einer unveränderlichen Funktion:
CREATE FUNCTION f_now_immutable()
RETURNS timestamp AS
$func$
SELECT now() AT TIME ZONE 'UTC' -- your time zone here
$func$ LANGUAGE sql IMMUTABLE;
Und dann:
select count(*) from events
where created_at > f_now_immutable() - interval '1 hour'
Seien Sie jedoch vorsichtig, wie Sie dies verwenden:while now()
ist STABLE
(ändert sich für die Dauer einer Transaktion nicht), es ändert zwischen Transaktionen ändern, achten Sie also darauf, dies nicht in vorbereiteten Anweisungen (außer als Parameterwert) oder Indizes oder irgendetwas zu verwenden, wo es Sie beißen könnte.
3.) Oder Sie können die scheinbar überflüssige Konstante WHERE
hinzufügen Klauseln zu Ihrer aktuellen Abfrage, die der Einschränkung Ihrer Partition entsprechen:
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;
Stellen Sie einfach selbst sicher, dass now() - '1 hour'::interval
fällt in die richtige Partition oder Sie erhalten offensichtlich keine Ergebnisse.
Übrigens:Ich würde diesen Ausdruck lieber in CHECK
verwenden Einschränkungen und Abfrage. Einfacher zu handhaben und tut dasselbe:
created_at >= '2015-04-01 0:0'::timestamp
AND created_at < '2015-05-01 0:0'::timestamp