2012-07-02 21 views
6

के बीच चयन करें मेरे पास 'YYYY-MM-DD' प्रारूप में दिनांक के रूप में कॉलम में से एक के साथ तालिका है। क्या मैं मासिक डेटा में सभी डेटा प्राप्त करने के लिए चयन का उपयोग कर सकता हूं? मान लें कि मैं 2012-01-xx से 2013-04-xx तक सभी डेटा चाहता हूं। इसलिए मैं मूल रूप से एक नीचे दिए गए जैसे एक SQL क्वेरी रहा हूँ:पोस्टग्रेस्क्ल महीने की श्रेणी

SELECT * FROM table WHERE date IN BETWEEN '2012-01' AND '2013-04' (INVALID QUERY) 

हर महीने के बाद से '01' के साथ शुरू मैं शुरू हालत समायोजित करने के लिए ऊपर क्वेरी संशोधित कर सकते हैं।

SELECT * FROM table WHERE date IN BETWEEN '2012-01-01' AND '2013-04' (INVALID QUERY) 

अब समस्या अंतराल के साथ आता है। मुझे दिए गए महीने की आखिरी तारीख को मैन्युअल रूप से गणना करना है, महीने की लंबाई, लीप वर्ष इत्यादि जैसे सभी कारकों को ध्यान में रखना, क्योंकि यदि दी गई तिथि अमान्य है तो क्वेरी विफल हो जाती है। तो वर्तमान में मैं ऐसा कुछ कर रहा हूं:

SELECT * FROM table WHERE date IN BETWEEN '2012-01-01' AND 'VALID_MONTH_END_DATE' (VALID Query) 

मैं जानना चाहता हूं कि इस वैध समाप्ति दिनांक गणना से बचने का कोई तरीका है या नहीं?

स्पष्टीकरण

मैं अगले महीने के पहले दिन से ऊपर नहीं सोचा है, लेकिन फिर भी मैं कुछ तर्क लागू करना होगा कहते हैं, अगर इसकी दिसंबर, अगले महीने अगले वर्ष जनवरी होगी। मैं जानना चाहता था कि एक एसक्यूएल केवल समाधान संभव है?

उत्तर

4

यह विवरण के वातावरण में एक बहुत ही आम जरूरत नहीं है।मैं कई कार्य बनाया है इन तारीख जोड़तोड़

CREATE OR REPLACE FUNCTION public.fn_getlastofmonth (
    date 
) 
RETURNS date AS 
$body$ 
begin 
    return (to_char(($1 + interval '1 month'),'YYYY-MM') || '-01')::date - 1; 
end; 
$body$ 
LANGUAGE 'plpgsql' 
VOLATILE 
CALLED ON NULL INPUT 
SECURITY INVOKER 
COST 100; 

तो आप उपयोग कर सकते समायोजित करने के लिए ...

WHERE date >= '2012-01-01' 
    AND date < fn_getlastofmonth('2013-04-01') 
10

दिनांक सीमा तुलना के लिए BETWEEN से बचना अच्छा है। >= और < का बेहतर उपयोग करें क्योंकि यह दिनांक और डेटाटाइम कॉलम/मानों के साथ समान रूप से काम करता है।

एक ही रास्ता (आप दिनांक बाह्य का निर्माण कर सकते हैं):

WHERE date >= DATE '2012-01-01' 
    AND date < DATE '2013-05-01'  --- first date of the next month 

आप उस तिथि के अंकगणित इस्तेमाल कर सकते हैं:

WHERE date >= DATE '2012-01-01' 
    AND date < DATE ('2013-04-01' + INTERVAL '1 MONTH') 

या OVERLAPS ऑपरेटर:

WHERE (date, date) OVERLAPS 
     (DATE '2012-01-01', DATE '2013-05-01') 

आप पोस्टग्रेज़ दस्तावेज भी पढ़ना चाहिए: Date/Time Functions and Operators

manual explains here क्यों OVERLAPS काम करता है इस तरह से:

हर बार की अवधि आधा खुला अंतराल का प्रतिनिधित्व करने के शुरू < = समय < अंत में, जब तक आरंभ और अंत में जो मामले में यह का प्रतिनिधित्व करता है के बराबर हैं माना जाता है वह एकल समय तत्काल। इसका मतलब यह है कि दो सामान्य अवधि में केवल एक अंतराल के साथ समय अवधि ओवरलैप नहीं होती है।

+0

ओवरलैप नहीं अच्छी तरह से जब मैं अंतिम तिथि पता काम करता है। पिछले महीने दिसंबर में मैं अटक गया हूं। –

+0

आप पैरामीटर कहां से प्राप्त करते हैं? एक आवेदन पत्र? मकड़जाल? एक और सवाल? क्या आपके पास तार या पूर्णांक (वर्ष, महीना) है? –

+1

'दिनांक' में 'अंतराल' जोड़ते समय देखभाल की जानी चाहिए। नतीजा एक 'टाइमस्टैम्प' है। हालांकि ऊपर दिए गए उदाहरण में काम करता है। यदि यह मायने रखता है, तो परिणाम को 'तिथि' पर कास्ट करें। एक अंतराल 'एन महीने' जोड़ना हमेशा उसी महीने के परिणामस्वरूप होता है, चाहे शामिल महीनों में वास्तविक दिनों की वास्तविक संख्या के बावजूद - या अधिकतम उपलब्ध दिन, जिसके परिणामस्वरूप महीने में कम दिन होते हैं। दिनों की सटीक संख्या जोड़ने के लिए, 'दिनांक' में 'पूर्णांक' जोड़ें, इसका परिणाम 'दिनांक' में होता है। –

0

सभी उत्तरों ऊपर एक काम कर समाधान प्रदान करते हैं, लेकिन एक ही रास्ता या अन्य में अधूरा है। चूंकि मैं एक एसक्यूएल केवल समाधान (कोई फंक्शन) की तलाश में था, इसलिए मैं ऊपर दिए गए समाधानों से सबसे अच्छी युक्तियों का संयोजन कर रहा हूं।

मेरे सवाल के लिए आदर्श समाधान होगा:

SELECT * FROM table 
WHERE date >= '2012-01-01' AND date < date('2013-04-01') + interval '1 month' 

संपादित

मैं ओवरलैप समारोह यहां उपयोग नहीं कर रहा है क्योंकि मैं 'युग के रूप में आरंभ और अंत के लिए डिफ़ॉल्ट दिनांक मान पास कर रहा हूँ ' और अब'। उपयोगकर्ता किसी भी समय सीमा निर्दिष्ट नहीं किया है, तो क्वेरी हो जाता है:

SELECT * FROM table 
WHERE date >= 'epoch' AND date < 'now' 

ओवरलैप समारोह 'युग' और 'अब' नहीं संभाल सकता है और देता है और एसक्यूएल त्रुटि जबकि इसके बाद के संस्करण कोड दोनों ही मामलों के लिए पूरी तरह से काम करते हैं।

पीएस: मैंने सभी उत्तरों को उखाड़ फेंक दिया है जो एक तरह से सही थे और मुझे इस समाधान के लिए प्रेरित किया।

+0

के बीच उपयोग करने की कोई आवश्यकता नहीं है मुझे लगता है कि आपको '- अंतराल' 1 दिन 'भाग को हटाने की आवश्यकता है। तालिका पर दिनांक '2013-04-30' तारीख के साथ इसे आजमाएं। –

+0

मैं मासिक डेटा की तलाश में हूं। मान लें कि मुझे कुछ साल, महीने से yyyy-mm तक सभी डेटा प्राप्त करने की आवश्यकता है। मेरी समाप्ति तिथि हमेशा yyyy-mm-01 है जिसमें मैं एक महीने जोड़ता हूं और एक दिन घटाता हूं। –

+1

बस क्वेरी का परीक्षण करें: 'चुनें * तालिका से जहां (दिनांक, तिथि) ओवरलैप्स (' 2012-01-01 ', तिथि (' 2013-04-01 ') + अंतराल' 1 महीने '- अंतराल' 1 दिन ') '' 2013-04-30' मूल्य के साथ तालिका में 'दिनांक' होने पर। क्या यह वापस आ गया है? –

0
SET search_path=tmp; 

DROP TABLE zdates; 
CREATE TABLE zdates 
     (zdate timestamp NOT NULL PRIMARY KEY 
     , val INTEGER NOT NULL 
     ); 
-- some data 
INSERT INTO zdates(zdate,val) 
SELECT s, 0 
FROM generate_series('2012-01-01', '2012-12-31', '1 day'::interval) s 
     ; 

UPDATE zdates 
SET val = 1000 * random(); 

DELETE FROM zdates 
WHERE random() < 0.1; 

-- CTE to round the intervals down/up to the begin/end of the month 
WITH zope AS (
     SELECT date_trunc('month', zdate)::date AS zbegin 
     , date_trunc('month', zdate+interval '1 month')::date AS zend 
     , val AS val 
     FROM zdates 
     ) 
SELECT z.zbegin 
     , z.zend 
     , COUNT(*) AS zcount 
     , SUM(val) AS zval 
FROM zope z 
GROUP BY z.zbegin, z.zend 
ORDER BY z.zbegin, z.zend 
     ; 

परिणाम:

CREATE TABLE 
INSERT 0 366 
UPDATE 366 
DELETE 52 
    zbegin | zend | zcount | zval 
------------+------------+--------+------- 
2012-01-01 | 2012-02-01 |  28 | 13740 
2012-02-01 | 2012-03-01 |  28 | 14923 
2012-03-01 | 2012-04-01 |  26 | 13775 
2012-04-01 | 2012-05-01 |  25 | 11880 
2012-05-01 | 2012-06-01 |  25 | 12693 
2012-06-01 | 2012-07-01 |  25 | 11082 
2012-07-01 | 2012-08-01 |  26 | 13254 
2012-08-01 | 2012-09-01 |  28 | 13632 
2012-09-01 | 2012-10-01 |  28 | 16461 
2012-10-01 | 2012-11-01 |  23 | 12622 
2012-11-01 | 2012-12-01 |  24 | 12554 
2012-12-01 | 2013-01-01 |  28 | 14563 
(12 rows) 
संबंधित मुद्दे