PostgreSQL में दो तिथियों के बीच समय श्रृंखला उत्पन्न करना


92

मेरे पास इस तरह से एक क्वेरी है जो अच्छी तरह से 2 दी गई तारीखों के बीच की एक श्रृंखला उत्पन्न करती है:

select date '2004-03-07' + j - i as AllDate 
from generate_series(0, extract(doy from date '2004-03-07')::int - 1) as i,
     generate_series(0, extract(doy from date '2004-08-16')::int - 1) as j

यह के बीच 162 दिनांक उत्पन्न करता है 2004-03-07और 2004-08-16और इस मैं क्या चाहते हैं। इस कोड के साथ समस्या यह है कि यह सही उत्तर नहीं देगा जब दो तिथियां अलग-अलग वर्षों से होती हैं, उदाहरण के लिए जब मैं कोशिश करता हूं 2007-02-01और 2008-04-01

क्या कोई बेहतर समाधान है?


जवाबों:


175

/ से रूपांतरण के बिना किया जा सकता है int से (लेकिन इसके बजाय / से टाइमस्टैम्प से)

SELECT date_trunc('day', dd):: date
FROM generate_series
        ( '2007-02-01'::timestamp 
        , '2008-04-01'::timestamp
        , '1 day'::interval) dd
        ;

3
क्यों date_truncजरूरी है?
इडेफिक्सक्स

2
यह सिर्फ प्रस्तुति है। यह टाइमस्टैम्प के समय भाग की छपाई को समाप्त कर देता है जो इस मामले में अल्वॉस जीरो है।
बेमेती

73

दिनांक की एक श्रृंखला उत्पन्न करने के लिए यह इष्टतम तरीका है:

SELECT t.day::date 
FROM   generate_series(timestamp '2004-03-07'
                     , timestamp '2004-08-16'
                     , interval  '1 day') AS t(day);
  • अतिरिक्त date_trunc()की जरूरत नहीं है। कास्ट date( day::date) ऐसा करता है।

  • लेकिन dateइनपुट पैरामीटर के रूप में दिनांक शाब्दिक कास्ट करने का कोई मतलब नहीं है । Au गर्भनिरोधक, timestampसबसे अच्छा विकल्प है । प्रदर्शन में लाभ छोटा है, लेकिन इसे नहीं लेने का कोई कारण नहीं है। और आप अनावश्यक रूप से डीएसटी (दिन के समय की बचत समय) के नियमों को शामिल नहीं करते हैं, dateजिससे timestamp with time zoneऔर पीछे से रूपांतरण हो जाता है । निचे देखो।

समतुल्य, कम स्पष्ट लघु वाक्य विन्यास:

SELECT day::date 
FROM   generate_series(timestamp '2004-03-07', '2004-08-16', '1 day') day;

या SELECTसूची में सेट-रिटर्न फ़ंक्शन के साथ :

SELECT generate_series(timestamp '2004-03-07', '2004-08-16', '1 day')::date AS day;

ASकीवर्ड है आवश्यक पिछले संस्करण में, Postgres स्तंभ उर्फ नादुस्र्स्ती से समझना होगा dayअन्यथा। और मैं यह सलाह नहीं दूंगा कि 10 से पहले वाले वेरिएंट - कम से कम एक ही SELECTसूची में एक से अधिक सेट-रिटर्निंग फंक्शन के साथ नहीं :

(एक तरफ, अंतिम संस्करण आमतौर पर एक छोटे से मार्जिन से सबसे तेज है।)

क्यों timestamp [without time zone]?

कई अतिभारित संस्करण हैं generate_series()। वर्तमान में (11 पोस्ट):

SELECT oid::regprocedure   AS function_signature
     , prorettype::regtype AS return_type
FROM   pg_proc
where  proname = 'generate_series';
function_signature | return_type                
: ------------------------------------------------- ------------------------------- | : --------------------------
Gener_series (पूर्णांक, पूर्णांक, पूर्णांक) | पूर्णांक                    
Gener_series (पूर्णांक, पूर्णांक) | पूर्णांक                    
Gener_series (bigint, bigint, bigint) | bigint                     
Gener_series (bigint, bigint) | bigint                     
Gener_series (संख्यात्मक, संख्यात्मक, संख्यात्मक) | संख्यात्मक                    
Gener_series (संख्यात्मक, संख्यात्मक) | संख्यात्मक                    
Gener_series (टाइम ज़ोन के बिना टाइमस्टैम्प, टाइम ज़ोन के बिना टाइमस्टैम्प, अंतराल) | टाइम ज़ोन के बिना टाइमस्टैम्प
Gener_series (टाइम ज़ोन के साथ टाइमस्टैम्प, टाइम ज़ोन के साथ टाइमस्टैम्प, अंतराल) | टाइम ज़ोन के साथ टाइमस्टैम्प

( numericवेरिएंट को पोस्टग्रेज 9.5 के साथ जोड़ा गया था।) संबंधित व्यक्ति बोल्ड लेने और लौटने timestamp/ में अंतिम दो हैं timestamptz

नहीं है कोई संस्करण लेने या लौटनेdate । लौटने के लिए एक स्पष्ट कलाकार की आवश्यकता होती है datetimestampतर्कों के साथ कॉल सीधे फ़ंक्शन प्रकार रिज़ॉल्यूशन नियमों में उतरने के बिना और इनपुट के लिए अतिरिक्त कलाकारों के बिना सबसे अच्छे संस्करण को हल करता है।

timestamp '2004-03-07'पूरी तरह से मान्य है, btw। 00:00आईएसओ प्रारूप के साथ छोड़े गए समय वाला भाग चूक जाता है ।

फ़ंक्शन प्रकार रिज़ॉल्यूशन के लिए धन्यवाद हम अभी भी पास कर सकते हैं date। लेकिन यह Postgres से अधिक काम की आवश्यकता है। वहाँ एक है निहित कलाकारों से dateकरने timestampसे एक के रूप में अच्छी तरह से dateकरने के लिए timestamptz। अस्पष्ट होगा, लेकिन timestamptzहै "पसंदीदा" "दिनांक / समय प्रकार" के बीच। इसलिए मैच 4d चरण में तय किया गया है :

सभी उम्मीदवारों के माध्यम से दौड़ें और उन लोगों को रखें जो सबसे अधिक पदों पर पसंदीदा प्रकार (इनपुट डेटा प्रकार के प्रकार की श्रेणी) को स्वीकार करते हैं जहां टाइप रूपांतरण की आवश्यकता होगी। सभी उम्मीदवार रखें यदि कोई भी पसंदीदा प्रकार स्वीकार नहीं करता है। यदि केवल एक उम्मीदवार रहता है, तो इसका उपयोग करें; अगले कदम के लिए जारी है।

फ़ंक्शन प्रकार रिज़ॉल्यूशन में अतिरिक्त कार्य के अलावा, इसमें एक अतिरिक्त कास्ट जोड़ा जाता है timestamptz- जो न केवल अधिक लागत जोड़ता है, बल्कि यह डीएसटी के साथ समस्याओं को भी पेश कर सकता है जो दुर्लभ मामलों में अप्रत्याशित परिणाम देता है। (डीएसटी एक नैतिक अवधारणा है, btw, यह पर्याप्त तनाव नहीं कर सकता है।) संबंधित:

मैंने फिडल में डेमो को और अधिक महंगी क्वेरी योजना दिखाते हुए जोड़ा:

db <> फिडल यहां

सम्बंधित:


7
और भी छोटे संस्करण:SELECT generate_series(timestamp '2004-03-07', '2004-08-16', '1 day') :: DATE AS day;
वल्कव कूज़ेल

T (दिन) वाक्यविन्यास क्या दर्शाता है?
Rendang

@rendang: AS t(day)में SELECT * FROM func() AS t(day)मेज और स्तंभ उर्फ कर रहे हैं। ASकीवर्ड इस संदर्भ में वैकल्पिक शोर है। देखें: stackoverflow.com/a/20230716/939860
इरविन ब्रांडस्टेटर

35

आप सीधे तारीखों के साथ श्रृंखला उत्पन्न कर सकते हैं। किलों या टाइमस्टैम्प का उपयोग करने की आवश्यकता नहीं है:

select date::date 
from generate_series(
  '2004-03-07'::date,
  '2004-08-16'::date,
  '1 day'::interval
) date;

आपके समय क्षेत्र के आधार पर, यह एक अप्रत्याशित परिणाम दे सकता है। मुझे यह समस्या थी। इसके बजाय टाइमस्टैम्प का उपयोग करें। SET सत्र टाइम ज़ोन 'अमेरिका / साओ_पाउलो' SELECT d :: date fromROM Gener_series ('2019-11-01' :: दिनांक, '2019-11-03' :: दिनांक, '1 दिन') d SELECT d :: date FROM generate_series ('2019-11-01' :: दिनांक, '2019-11-04' :: दिनांक, '1 दिन') d
palhares

1

आप भी इसका इस्तेमाल कर सकते हैं।

select generate_series  ( '2012-12-31'::timestamp , '2018-10-31'::timestamp , '1 day'::interval) :: date 
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.