PostgreSQL में संचयी योग की गणना


85

मैं संचयी या चलने वाली राशि का पता लगाना चाहता हूं और इसे मंचन से तालिका में सम्मिलित करना चाहता हूं। मेरा मंचन संरचना कुछ इस प्रकार है:

ea_month    id       amount    ea_year    circle_id
April       92570    1000      2014        1
April       92571    3000      2014        2
April       92572    2000      2014        3
March       92573    3000      2014        1
March       92574    2500      2014        2
March       92575    3750      2014        3
February    92576    2000      2014        1
February    92577    2500      2014        2
February    92578    1450      2014        3          

मैं चाहता हूं कि मेरी लक्ष्य तालिका कुछ इस तरह दिखे:

ea_month    id       amount    ea_year    circle_id    cum_amt
February    92576    1000      2014        1           1000 
March       92573    3000      2014        1           4000
April       92570    2000      2014        1           6000
February    92577    3000      2014        2           3000
March       92574    2500      2014        2           5500
April       92571    3750      2014        2           9250
February    92578    2000      2014        3           2000
March       92575    2500      2014        3           4500
April       92572    1450      2014        3           5950

मैं वास्तव में बहुत उलझन में हूं कि इस परिणाम को कैसे प्राप्त किया जाए। मैं PostgreSQL का उपयोग करके इस परिणाम को प्राप्त करना चाहता हूं।

क्या कोई सुझाव दे सकता है कि इस परिणाम को प्राप्त करने के बारे में कैसे जाना जाए?


1
आपको अपनी लक्ष्य तालिका में 1000 का सह_माउंट कैसे मिलता है? Circle_id के लिए, राशि 2000 लगती है।

जवाबों:


130

मूल रूप से, आपको एक विंडो फ़ंक्शन की आवश्यकता है । यही आजकल एक मानक विशेषता है। वास्तविक विंडो फ़ंक्शंस के अलावा, आप किसी भीOVER क्लाज़ को जोड़कर Postgres में विंडो फ़ंक्शन के रूप में किसी भी कुल फ़ंक्शन का उपयोग कर सकते हैं ।

यहाँ विशेष कठिनाई विभाजन और क्रम क्रम को प्राप्त करना है:

SELECT ea_month, id, amount, ea_year, circle_id
     , sum(amount) OVER (PARTITION BY circle_id
                         ORDER BY ea_year, ea_month) AS cum_amt
FROM   tbl
ORDER  BY circle_id, month;

और नहीं GROUP BY

प्रत्येक पंक्ति के लिए राशि की गणना विभाजन में पहली पंक्ति से वर्तमान पंक्ति तक की जाती है - या मैनुअल को सटीक बताते हुए:

डिफ़ॉल्ट फ्रेमिंग विकल्प है RANGE UNBOUNDED PRECEDING, जो कि जैसा है वैसा ही है RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW। इसके साथ ORDER BY, यह फ्रेम को विभाजन से सभी पंक्तियों को चालू करने के लिए वर्तमान पंक्ति के अंतिम ORDER BYपीयर के माध्यम से सेट करता है ।

... जो संचयी या चलने का योग है, उसके बाद आप हैं। बोल्ड जोर मेरा।

एक ही साथ वाली पंक्तियां (circle_id, ea_year, ea_month)हैं "साथियों" इस क्वेरी में। उन सभी को सभी साथियों के साथ एक ही रनिंग योग दिखाई देता है। लेकिन मुझे लगता है कि आपकी तालिका UNIQUEचालू है (circle_id, ea_year, ea_month), तो क्रम क्रम नियतात्मक है और किसी पंक्ति में सहकर्मी नहीं हैं।

अब, ORDER BY ... ea_month महीने के नामों के लिए तार के साथ काम नहीं करेंगे । स्थानीय सेटिंग के अनुसार, वर्णानुक्रम में वर्णानुक्रम में छाँटे जाएंगे।

यदि आपके पास dateअपनी तालिका में वास्तविक मान संग्रहीत हैं, तो आप ठीक से सॉर्ट कर सकते हैं। यदि नहीं, तो मैं बदलने के लिए सुझाव देते हैं ea_yearऔर ea_monthएक एकल स्तंभ के साथ monप्रकार की dateअपनी तालिका में।

  • आपके पास जो है उसे ट्रांसफ़ॉर्म करें to_date():

      to_date(ea_year || ea_month , 'YYYYMonth') AS mon
    
  • प्रदर्शन के लिए, आप इसके साथ मूल तार प्राप्त कर सकते हैं to_char():

      to_char(mon, 'Month') AS ea_month
      to_char(mon, 'YYYY') AS ea_year
    

हालांकि दुर्भाग्यपूर्ण डिजाइन के साथ, यह काम करेगा:

SELECT ea_month, id, amount, ea_year, circle_id
     , sum(amount) OVER (PARTITION BY circle_id ORDER BY mon) AS cum_amt
FROM   (SELECT *, to_date(ea_year || ea_month, 'YYYYMonth') AS mon FROM tbl)
ORDER  BY circle_id, mon;

समाधान के लिए धन्यवाद .. क्या आप मेरी एक और बात की मदद कर सकते हैं। मैं एक ही बात को लागू करना चाहता हूं कि एक कर्सर का उपयोग करके तर्क दिया जा सकता है कि हर सर्कल में साल के एक महीने के लिए सिर्फ एक रिकॉर्ड होगा। और फंक्शन हर महीने में एक बार चलना चाहिए। इसे कैसे प्राप्त किया जा सकता है?
यूसुफ सुल्तान

4
@ युसूफसुल्तान: ज्यादातर समय एक कर्सर की तुलना में बेहतर समाधान होता है। यह निश्चित रूप से एक नए प्रश्न के लिए सामान है। कृपया एक नया प्रश्न शुरू करें।
इरविन ब्रान्डसेट्टर

मुझे कम से कम एक नोट के बिना यह उत्तर अधूरा लगता है कि यहां "फ्रेमिंग" चल रही है जो कि चूक करता है range unbounded preceding, जो कि जैसा है वैसा ही है range between unbounded preceding and current row। यही कारण है कि sum()जब एक विंडो फ़ंक्शन के रूप में उपयोग किया जाता है, तो कुल रनिंग का उत्पादन होता है - जबकि अन्य विंडो फ़ंक्शंस में यह डिफ़ॉल्ट फ़्रेम नहीं होता है।
कॉलिन टी हार्ट

1
@ Colin'tHart: मैंने स्पष्ट करने के लिए कुछ और ऊपर जोड़ा।
इरविन ब्रान्डस्टेट्टर

यहां एक सरल प्रश्न के साथ इसी तरह के प्रश्न का लिंक दिया गया PARTITIONहै ( हमेशा चलने वाले कुल बनाने के लिए आवश्यक नहीं है): stackoverflow.com/a/5700744/175830
जेसन एक्सेलसन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.