Din kolumn created_at
är timestamp without time zone
.
Men now()
returnerar timestamp with time zone
. Uttrycket now() - '1 hour'::interval
tvingas till timestamp [without time zone]
, som har två problem :
1.) Du frågade inte efter den här, men uttrycket är opålitligt. Resultatet beror på den aktuella tidszonsinställningen för sessionen som frågan körs i. Detaljer här:
För att göra uttrycket tydligt kan du använda:
now() AT TIME ZONE 'Europe/London' -- your time zone here
Eller bara (läs manualen här) :
LOCALTIMESTAMP -- explicitly take the local time
Jag skulle överväga att arbeta med timestamptz
istället.
Ingen av dem löser ditt andra problem:
2.) Svar på din fråga. Uteslutning av begränsningar fungerar inte. Per dokumentation:
Djärv betoning min.
now()
är Postgres-implementeringen av CURRENT_TIMESTAMP
. Som du kan se i systemkatalogen är den bara STABLE
, inte IMMUTABLE
:
SELECT proname, provolatile FROM pg_proc WHERE proname = 'now';
proname | provolatile
--------+------------
now | s -- meaning: STABLE
Lösningar
1.) Du kan övervinna begränsningen genom att ange en konstant i WHERE
villkor (som alltid är "oföränderligt"):
select count(*) from events
where created_at > '2015-05-25 15:49:20.037815'::timestamp; -- derived from your example
2.) Eller genom att "fejka" en oföränderlig funktion:
CREATE FUNCTION f_now_immutable()
RETURNS timestamp AS
$func$
SELECT now() AT TIME ZONE 'UTC' -- your time zone here
$func$ LANGUAGE sql IMMUTABLE;
Och sedan:
select count(*) from events
where created_at > f_now_immutable() - interval '1 hour'
Var dock försiktig med hur du använder detta:while now()
är STABLE
(ändras inte under en transaktions varaktighet), gör det det växla mellan transaktioner, så se till att inte använda detta i förberedda uttalanden (förutom som parametervärde) eller index eller något där det kan bita dig.
3.) Eller så kan du lägga till en till synes redundant konstant WHERE
satser till din nuvarande fråga som matchar begränsningen på din partition:
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;
Se bara till att now() - '1 hour'::interval
faller in i rätt partition eller så får du inga resultat, uppenbarligen.
Bortsett från:Jag skulle hellre använda detta uttryck i CHECK
begränsningar och fråga. Lättare att hantera och gör detsamma:
created_at >= '2015-04-01 0:0'::timestamp
AND created_at < '2015-05-01 0:0'::timestamp