Postgresql में डेटाइम फ़ील्ड में दिनांक की तुलना कैसे करें?


188

मैं एक अजीब परिदृश्य का सामना कर रहा हूं, जब पोस्टग्रेज़ल (विंडोज़ में संस्करण 9.2.4) में तारीखों के बीच तुलना की गई है। मेरे पास अपनी तालिका में एक कॉलम है 'update_date' टाइप टाइमस्टैम्प विदाउट टाइमज़ोन। ग्राहक केवल दिनांक (यानी: 2013-05-03) या समय के साथ दिनांक (यानी: 2013-05-03 12:20:00) के साथ इस क्षेत्र में खोज कर सकते हैं। इस स्तंभ में वर्तमान में सभी पंक्तियों के लिए टाइमस्टैम्प के रूप में मान है और दिनांक दिनांक (2013-05-03) समान है लेकिन समय भाग में अंतर है।

जब मैं इस कॉलम की तुलना कर रहा हूं, तो मुझे अलग परिणाम मिल रहे हैं। अनुगमन की तरह:

select * from table where update_date >= '2013-05-03' AND update_date <= '2013-05-03' -> No results

select * from table where update_date >= '2013-05-03' AND update_date < '2013-05-03' -> No results

select * from table where update_date >= '2013-05-03' AND update_date <= '2013-05-04' -> results found

select * from table where update_date >= '2013-05-03' -> results found

मेरा सवाल यह है कि मैं परिणाम प्राप्त करने के लिए पहली क्वेरी कैसे संभव कर सकता हूं, मेरा मतलब है कि तीसरी क्वेरी क्यों काम कर रही है लेकिन पहले वाली नहीं?

क्या कोई मेरी इसके साथ मदद कर सकता है? अग्रिम में धन्यवाद।

जवाबों:


279

@ निकोलई कास्टिंग के बारे में सही है और किसी भी डेटा के लिए स्थिति झूठी क्यों है। मुझे लगता है कि आप पहले फॉर्म को पसंद करते हैं क्योंकि आप इनपुट स्ट्रिंग पर डेट हेरफेर से बचना चाहते हैं, सही है? आपको डरने की जरूरत नहीं है:

SELECT *
FROM table
WHERE update_date >= '2013-05-03'::date
AND update_date < ('2013-05-03'::date + '1 day'::interval);

क्या यह वाक्यविन्यास ( '2013-05-03'::dateऔर '1 day'::interval) पोस्टग्रेक्सेल विशिष्ट है?
जमे हुए लौ

5
@FrozenFlame हाँ यह है। मानक वाक्यविन्यास CAST('2013-05-03' AS DATE) + CAST('1 day' AS INTERVAL)(IIRC) होगा। के अस्तित्व और व्यवहार पर YMMV DATEऔर INTERVAL
बस किसी

@FrozenFlame सही है, स्ट्रिंग्स को तिथि प्रकारों के कास्टिंग के बिना जवाब काम नहीं करता है। एक कास्ट अभी भी लापता है। वहाँ एक होने की जरूरत है ::DATE, जहां खंड के पहले भाग को जोड़ा गया
StillLearningToCode

के WHERE update_date::date = '2013-05-03' रूप में अच्छी तरह से और शायद थोड़ा अधिक पठनीय काम नहीं करेगा ?
माइक एफएफ

@ मायकेएफ ओपी ने कहा update_dateथा timestamp without timezone। मैंने उस कॉलम पर एक इंडेक्स ग्रहण किया। आपका विधेय उस सूचकांक का उपयोग नहीं करेगा।
बस

46

जब आप तुलना करते हैं तो update_date >= '2013-05-03'मूल्यों की तुलना करने के लिए उसी प्रकार के मूल्यों को पोस्टग्रेट करते हैं। इसलिए आपकी '2013-05-03' को '2013-05-03 00:00:00' पर कास्ट किया गया।

तो update_date = '2013-05-03 14:45:00' के लिए आपकी अभिव्यक्ति यही होगी:

'2013-05-03 14:45:00' >= '2013-05-03 00:00:00' AND '2013-05-03 14:45:00' <= '2013-05-03 00:00:00'

यह हमेशा से है false

इस समस्या को हल करने के लिए अद्यतन करें date:

select * from table where update_date::date >= '2013-05-03' AND update_date::date <= '2013-05-03' -> Will return result

1
update_dateतालिका में प्रत्येक को डालना बनाम क्वेरी पैरामीटर के एकल मान को डालना बहुत ही अक्षम है, और यह सुनिश्चित करता है कि सर्वर उस स्तंभ पर अनुक्रमित का लाभ उठाने में सक्षम नहीं होगा। मुझे यह -1 लुभा रहा है।
बस

3
हां, मैं मानता हूं कि प्रत्येक मूल्य की कास्टिंग अक्षम है और आप इस समाधान के लिए -1 दे सकते हैं। लेकिन मैंने समस्या का कारण बताया और उदाहरण दिया कि इस मुद्दे को प्रदर्शित करता है। अब user2866264 को पता है कि उसकी क्वेरी अपेक्षित पंक्तियों को वापस क्यों नहीं करती है और यह तय करेगी कि उसके अनूठे मामले के लिए वास्तव में क्या समाधान बेहतर है।
निकोलई

@ नाइकोलाई: आपके उत्तर के लिए बहुत बहुत धन्यवाद। यह आपके उत्तर का अनुसरण करके काम करता है। स्पष्टीकरण के लिए भी धन्यवाद।
user2866264

1
@ निकोलाई - यह देखते हुए कि आपने पोस्टग्रेट्स के बारे में क्या कहा है, मध्यरात्रि के स्ट्रोक के लिए तारीख शाब्दिक रूप से विस्तारित हो रही है, यदि लक्ष्य एक ही तारीख (3 मई) को चिह्नित रिकॉर्ड पा रहा है, तो क्या यह कोड सही और अधिक कुशल होगा: SELECT * FROM my_table WHERE update_date >= '2013-05-03' AND update_date < '2013-05-04'; (4 मई के उपयोग पर ध्यान दें) 3 जी के बजाय और कम-से-या-बराबर के बजाय एक LESS-THAN SIGN के साथ।)
बेसिल बोर्क

9

rangeप्रकार का उपयोग करें । यदि उपयोगकर्ता एक तारीख दर्ज करता है:

select *
from table
where
    update_date
    <@
    tsrange('2013-05-03', '2013-05-03'::date + 1, '[)');

यदि उपयोगकर्ता टाइमस्टैम्प में प्रवेश करता है, तो आपको ::date + 1भाग की आवश्यकता नहीं है

http://www.postgresql.org/docs/9.2/static/rangetypes.html

http://www.postgresql.org/docs/9.2/static/functions-range.html


यह एक दिलचस्प और दिलचस्प जवाब है!
युरिप्लोक

2

दिनांक के साथ तुलना करने के लिए दिनांक कन्वर्ट का उपयोग करें: यह कोशिश करें:

select * from table 
where TO_DATE(to_char(timespanColumn,'YYYY-MM-DD'),'YYYY-MM-DD') = to_timestamp('2018-03-26', 'YYYY-MM-DD')
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.