Uw kolom created_at
is timestamp without time zone
.
Maar now()
retourneert timestamp with time zone
. De uitdrukking now() - '1 hour'::interval
wordt gedwongen tot timestamp [without time zone]
, met twee problemen :
1.) Je hebt hier niet om gevraagd, maar de uitdrukking is onbetrouwbaar. Het resultaat hangt af van de huidige tijdzone-instelling van de sessie waarin de query wordt uitgevoerd. Details hier:
Om de uitdrukking duidelijk te maken, kunt u het volgende gebruiken:
now() AT TIME ZONE 'Europe/London' -- your time zone here
Of gewoon (lees de handleiding hier) :
LOCALTIMESTAMP -- explicitly take the local time
Ik zou overwegen om te werken met timestamptz
in plaats daarvan.
Geen van beide lost uw tweede probleem op:
2.) Antwoord op uw vraag. Beperking uitsluiting werkt niet. Per documentatie:
Vetgedrukte nadruk van mij.
now()
is de Postgres-implementatie van CURRENT_TIMESTAMP
. Zoals je kunt zien in de systeemcatalogus, is het alleen STABLE
, niet IMMUTABLE
:
SELECT proname, provolatile FROM pg_proc WHERE proname = 'now';
proname | provolatile
--------+------------
now | s -- meaning: STABLE
Oplossingen
1.) U kunt de beperking omzeilen door een constante op te geven in de WHERE
voorwaarde (die altijd "onveranderlijk" is):
select count(*) from events
where created_at > '2015-05-25 15:49:20.037815'::timestamp; -- derived from your example
2.) Of door een onveranderlijke functie te "faken":
CREATE FUNCTION f_now_immutable()
RETURNS timestamp AS
$func$
SELECT now() AT TIME ZONE 'UTC' -- your time zone here
$func$ LANGUAGE sql IMMUTABLE;
En dan:
select count(*) from events
where created_at > f_now_immutable() - interval '1 hour'
Wees echter voorzichtig met hoe je dit gebruikt:while now()
is STABLE
(verandert niet voor de duur van een transactie), wel wissel tussen transacties, dus zorg ervoor dat u dit niet gebruikt in voorbereide verklaringen (behalve als parameterwaarde) of indexen of iets anders waar het u zou kunnen bijten.
3.) Of je kunt schijnbaar overbodige constante WHERE
. toevoegen clausules voor uw huidige zoekopdracht die overeenkomen met de beperking op uw partitie:
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;
Zorg ervoor dat u now() - '1 hour'::interval
valt in de juiste partitie of je krijgt natuurlijk geen resultaten.
Terzijde:ik zou deze uitdrukking liever gebruiken in CHECK
beperkingen en vragen. Makkelijker te hanteren en doet hetzelfde:
created_at >= '2015-04-01 0:0'::timestamp
AND created_at < '2015-05-01 0:0'::timestamp