La tua colonna created_at
è timestamp without time zone
.
Ma now()
restituisce timestamp with time zone
. L'espressione now() - '1 hour'::interval
viene costretto a timestamp [without time zone]
, che comporta due problemi :
1.) Non hai chiesto questo, ma l'espressione è inaffidabile. Il risultato dipende dall'impostazione del fuso orario corrente della sessione in cui viene eseguita la query. Dettagli qui:
Per rendere chiara l'espressione, potresti usare:
now() AT TIME ZONE 'Europe/London' -- your time zone here
O semplicemente (leggi il manuale qui) :
LOCALTIMESTAMP -- explicitly take the local time
Prenderei in considerazione l'idea di lavorare con timestamptz
invece.
Nessuno risolve il tuo secondo problema:
2.) Rispondi alla tua domanda. L'esclusione dei vincoli non funziona. Per documentazione:
Enfasi in grassetto la mia.
now()
è l'implementazione Postgres di CURRENT_TIMESTAMP
. Come puoi vedere nel catalogo del sistema, è solo STABLE
, non IMMUTABLE
:
SELECT proname, provolatile FROM pg_proc WHERE proname = 'now';
proname | provolatile
--------+------------
now | s -- meaning: STABLE
Soluzioni
1.) Puoi superare la limitazione fornendo una costante in WHERE
condizione (che è sempre "immutabile"):
select count(*) from events
where created_at > '2015-05-25 15:49:20.037815'::timestamp; -- derived from your example
2.) O "fingendo" una funzione immutabile:
CREATE FUNCTION f_now_immutable()
RETURNS timestamp AS
$func$
SELECT now() AT TIME ZONE 'UTC' -- your time zone here
$func$ LANGUAGE sql IMMUTABLE;
E poi:
select count(*) from events
where created_at > f_now_immutable() - interval '1 hour'
Fai attenzione a come lo usi:while now()
è STABLE
(non cambia per la durata di una transazione), fa cambiare tra le transazioni, quindi fai attenzione a non usarlo in dichiarazioni preparate (tranne come valore di parametro) o indici o qualsiasi cosa in cui potrebbe morderti.
3.) Oppure puoi aggiungere una costante apparentemente ridondante WHERE
clausole alla query corrente che corrispondono al vincolo sulla partizione:
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;
Assicurati solo che now() - '1 hour'::interval
cade nella partizione giusta o non ottieni risultati, ovviamente.
A parte:preferirei usare questa espressione in CHECK
vincoli e interrogazione. Più facile da maneggiare e fa lo stesso:
created_at >= '2015-04-01 0:0'::timestamp
AND created_at < '2015-05-01 0:0'::timestamp