आपका कॉलम created_at
timestamp without time zone
।
लेकिन now()
रिटर्न timestamp with time zone
. व्यंजक now() - '1 hour'::interval
timestamp [without time zone]
के लिए ज़बरदस्ती किया जा रहा है , जिसमें दो समस्याएं हैं :
1.) आपने इसके लिए नहीं पूछा, लेकिन अभिव्यक्ति अविश्वसनीय है। इसका परिणाम उस सत्र की वर्तमान समय क्षेत्र सेटिंग पर निर्भर करता है जिसमें क्वेरी निष्पादित की जा रही है। यहां विवरण:
अभिव्यक्ति को स्पष्ट करने के लिए, आप इसका उपयोग कर सकते हैं:
now() AT TIME ZONE 'Europe/London' -- your time zone here
या बस (मैनुअल यहां पढ़ें)ए> :
LOCALTIMESTAMP -- explicitly take the local time
मैं timestamptz
. के साथ काम करने पर विचार करूंगा इसके बजाय।
न तो आपकी दूसरी समस्या का समाधान करता है:
2.) आपके प्रश्न का उत्तर दें। प्रतिबंध बहिष्करण काम नहीं करता है। प्रति दस्तावेज़:
बोल्ड जोर मेरा।
now()
CURRENT_TIMESTAMP
. का पोस्टग्रेज कार्यान्वयन है . जैसा कि आप सिस्टम कैटलॉग में देख सकते हैं, यह केवल STABLE
है , नहीं IMMUTABLE
:
SELECT proname, provolatile FROM pg_proc WHERE proname = 'now';
proname | provolatile
--------+------------
now | s -- meaning: STABLE
समाधान
1.) आप WHERE
. में एक स्थिरांक प्रदान करके सीमा को पार कर सकते हैं शर्त (जो हमेशा "अपरिवर्तनीय" होती है):
select count(*) from events
where created_at > '2015-05-25 15:49:20.037815'::timestamp; -- derived from your example
2.) या एक अपरिवर्तनीय फ़ंक्शन को "नकली" करके:
CREATE FUNCTION f_now_immutable()
RETURNS timestamp AS
$func$
SELECT now() AT TIME ZONE 'UTC' -- your time zone here
$func$ LANGUAGE sql IMMUTABLE;
और फिर:
select count(*) from events
where created_at > f_now_immutable() - interval '1 hour'
हालांकि सावधान रहें कि आप इसका उपयोग कैसे करते हैं:जबकि now()
STABLE
है (लेन-देन की अवधि के लिए नहीं बदलता), यह करता है लेन-देन के बीच परिवर्तन, इसलिए ध्यान रखें कि इसे तैयार किए गए बयानों (पैरामीटर मान को छोड़कर) या अनुक्रमणिका या ऐसी किसी भी चीज़ में उपयोग न करें जहाँ यह आपको काट सकता है।
3.) या आप प्रतीत होता है कि बेमानी स्थिरांक जोड़ सकते हैं WHERE
आपकी वर्तमान क्वेरी के खंड जो आपके विभाजन की बाधा से मेल खाते हैं:
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;
बस स्वयं सुनिश्चित करें कि now() - '1 hour'::interval
सही विभाजन में पड़ता है या आपको कोई परिणाम नहीं मिलता है, जाहिर है।
इसके अलावा:मैं इस अभिव्यक्ति का उपयोग CHECK
. में करना चाहूंगा बाधाएं और क्वेरी। संभालना आसान और वही करता है:
created_at >= '2015-04-01 0:0'::timestamp
AND created_at < '2015-05-01 0:0'::timestamp