Twoja kolumna created_at to timestamp without time zone .
Ale now() zwraca timestamp with time zone . Wyrażenie now() - '1 hour'::interval jest zmuszany do timestamp [without time zone] , co niesie ze sobą dwa problemy :
1.) Nie prosiłeś o to, ale wyrażenie jest niewiarygodne. Jego wynik zależy od aktualnego ustawienia strefy czasowej sesji, w której wykonywane jest zapytanie. Szczegóły tutaj:
Aby wyrażenie było jasne, możesz użyć:
now() AT TIME ZONE 'Europe/London' -- your time zone here
Lub po prostu (przeczytaj instrukcję tutaj) :
LOCALTIMESTAMP -- explicitly take the local time
Rozważę pracę z timestamptz zamiast tego.
Żadne z nich nie rozwiązuje drugiego problemu:
2.) Odpowiedz na Twoje pytanie. Wykluczenie ograniczeń nie działa. Zgodnie z dokumentacją:
Pogrubiony nacisk na moje.
now() jest implementacją Postgresa CURRENT_TIMESTAMP . Jak widać w katalogu systemowym, jest on tylko STABLE , a nie IMMUTABLE :
SELECT proname, provolatile FROM pg_proc WHERE proname = 'now';
proname | provolatile
--------+------------
now | s -- meaning: STABLE
Rozwiązania
1.) Możesz obejść to ograniczenie, podając stałą w WHERE warunek (który jest zawsze "niezmienny"):
select count(*) from events
where created_at > '2015-05-25 15:49:20.037815'::timestamp; -- derived from your example
2.) Lub „udając” niezmienną funkcję:
CREATE FUNCTION f_now_immutable()
RETURNS timestamp AS
$func$
SELECT now() AT TIME ZONE 'UTC' -- your time zone here
$func$ LANGUAGE sql IMMUTABLE;
A potem:
select count(*) from events
where created_at > f_now_immutable() - interval '1 hour'
Uważaj jednak, jak tego używasz:podczas gdy now() jest STABLE (nie zmienia się w czasie trwania transakcji), zmienia się zmieniać między transakcjami, więc uważaj, aby nie używać tego w przygotowanych instrukcjach (z wyjątkiem wartości parametru) lub indeksów lub czegokolwiek, co może cię ugryźć.
3.) Lub możesz dodać pozornie nadmiarową stałą WHERE klauzule do bieżącego zapytania, które pasują do ograniczenia na Twojej partycji:
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;
Upewnij się tylko, że now() - '1 hour'::interval wpadnie do właściwej partycji lub oczywiście nie uzyskasz żadnych wyników.
Poza tym:wolałbym użyć tego wyrażenia w CHECK ograniczenia i zapytanie. Łatwiejszy w obsłudze i robi to samo:
created_at >= '2015-04-01 0:0'::timestamp
AND created_at < '2015-05-01 0:0'::timestamp