2012-01-13 19 views
10

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

SELECT p.name, e.date, 
    sum(sp.payout) OVER (ORDER BY e.date) 
    - sum(s.buyin) OVER (ORDER BY e.date) AS "Profit/Loss" 
FROM result r 
    JOIN game g ON r.game_id = g.game_id 
    JOIN event e ON g.event_id = e.event_id 
    JOIN structure s ON g.structure_id = s.structure_id 
    JOIN structure_payout sp ON g.structure_id = sp.structure_id 
          AND r.position = sp.position 
    JOIN player p ON r.player_id = p.player_id 
WHERE p.player_id = 17 
GROUP BY p.name, e.date, e.event_id, sp.payout, s.buyin 
ORDER BY p.name, e.date ASC 

क्वेरी चलेंगे:

क्वेरी मैं अब तक राशि है। हालांकि, परिणाम थोड़ा गलत है। कारण यह है कि event में कई गेम हो सकते हैं (विभिन्न sp.payouts के साथ)। इसलिए, उपर्युक्त कई पंक्तियों के साथ आता है यदि उपयोगकर्ता के पास अलग-अलग पेआउट वाले ईवेंट में 2 परिणाम होते हैं (यानी प्रति ईवेंट 4 गेम होते हैं, और उपयोगकर्ता को एक से £ 20 और दूसरे से £ 40 मिलते हैं)।

स्पष्ट समाधान में संशोधन करने का GROUP BY होगा:

GROUP BY p.name, e.date, e.event_id 

हालांकि, Postgres इस पर शिकायत रूप में पहचान किया जाना चाहिए कि sp.payout और s.buyin एक समग्र समारोह के अंदर हैं प्रकट नहीं होता है। मुझे त्रुटि मिलती है:

column "sp.payout" must appear in the GROUP BY clause or be used in an aggregate function

मैं उबंटू लिनक्स सर्वर पर 9.1 चला रहा हूं।
क्या मुझे कुछ याद आ रहा है, या क्या यह पोस्टग्रेस में वास्तविक दोष हो सकता है?

उत्तर

21

आप नहीं हैं, वास्तव में, कुल कार्यों का उपयोग करते हुए। आप window functions का उपयोग कर रहे हैं। यही कारण है कि 0gखंड में PostgreSQL sp.payout और s.buyin की मांग करता है।

एक OVER खंड जोड़कर, समेकित फ़ंक्शन sum() एक खिड़की समारोह है, जो विभाजन प्रति मूल्यों को एकत्रित करती है, जबकि सभी पंक्तियों रखने में बदल गया है।

आप विंडो फ़ंक्शंस और समेकित कार्यों को जोड़ सकते हैं। समेकन पहले लागू होते हैं। मुझे आपके विवरण से समझ में नहीं आया कि आप प्रति ईवेंट एकाधिक पेआउट/खरीदार कैसे संभालना चाहते हैं। एक अनुमान के रूप में, मैं प्रति घटना के योग की गणना करता हूं। अब मैं GROUP BY खंड से sp.payout और s.buyin हटाने और player और event प्रति एक पंक्ति प्राप्त कर सकते हैं:

SELECT p.name 
    , e.event_id 
    , e.date 
    , sum(sum(sp.payout)) OVER w 
    - sum(sum(s.buyin )) OVER w AS "Profit/Loss" 
FROM player   p 
JOIN result   r ON r.player_id  = p.player_id 
JOIN game    g ON g.game_id  = r.game_id 
JOIN event    e ON e.event_id  = g.event_id 
JOIN structure   s ON s.structure_id = g.structure_id 
JOIN structure_payout sp ON sp.structure_id = g.structure_id 
          AND sp.position  = r.position 
WHERE p.player_id = 17 
GROUP BY e.event_id 
WINDOW w AS (ORDER BY e.date, e.event_id) 
ORDER BY e.date, e.event_id; 

इस एक्सप्रेशन में: sum(sum(sp.payout)) OVER w, बाहरी sum() एक खिड़की समारोह है, भीतरी sum() एक समग्र समारोह है ।

मानते हैं कि p.player_id और e.event_idPRIMARY KEY उनके संबंधित तालिकाओं में हैं।

मैंने e.event_idORDER BYWINDOW क्लॉज को एक निर्धारित क्रम क्रम पर पहुंचने के लिए जोड़ा। (उसी तारीख पर कई घटनाएं हो सकती हैं।) प्रति दिन कई घटनाओं को अलग करने के परिणामस्वरूप event_id भी शामिल है।

क्वेरी एक एकल खिलाड़ी (WHERE p.player_id = 17) को प्रतिबंधित करते हैं, हम GROUP BY और ORDER BY को p.name या p.player_id जोड़ने की जरूरत नहीं है। यदि जुड़ने वालों में से एक पंक्तियों को अनावश्यक रूप से गुणा करेगी, परिणामी राशि गलत होगी (आंशिक रूप से या पूरी तरह से गुणा)। p.name द्वारा ग्रुपिंग तब क्वेरी की मरम्मत नहीं कर सका।

मैंने खंड से e.date को भी हटा दिया। प्राथमिक कुंजी e.event_id इनपुट पंक्ति since PostgreSQL 9.1 के सभी कॉलम को शामिल करती है।

हैं आप क्वेरी को परिवर्तित एक साथ कई खिलाड़ियों वापस जाने के लिए, अनुकूलन: (?)

... 
WHERE p.player_id < 17 -- example - multiple players 
GROUP BY p.name, p.player_id, e.date, e.event_id -- e.date and p.name redundant 
WINDOW w AS (ORDER BY p.name, p.player_id, e.date, e.event_id) 
ORDER BY p.name, p.player_id, e.date, e.event_id; 

जब तक p.name अद्वितीय परिभाषित किया गया है, समूह और व्यवस्था player_id द्वारा इसके अलावा एक में सही परिणाम प्राप्त करने के निर्धारिक क्रम क्रम।

मैंने e.date और p.name में सभी खंडों में समान क्रम क्रम रखने के लिए केवल प्रदर्शन लाभ की उम्मीद करते हुए रखा था। अन्यथा, आप वहां कॉलम हटा सकते हैं। (पहली क्वेरी में केवल e.date के लिए इसी तरह।)

+0

पहली क्वेरी काम कर रही है, हालांकि, क्वेरी का आउटपुट आवश्यक परिणाम नहीं दे रहा है। मैं देख सकता हूं कि सिद्धांत में सिद्धांत क्या काम करेगा, लेकिन पोस्टग्रेस इसे पसंद नहीं करते हैं। मैं बाद में कोशिश करूँगा और आपको बता दूंगा। हालांकि, ऐसा लगता है कि "event_id" में एक से अधिक "पेआउट" राशि होने पर आपकी क्वेरी के आउटपुट में 2 पंक्तियां होंगी। – Martin

+0

मैंने अभी आपके द्वारा सुझाए गए संशोधनों के साथ प्रयास किया है, और यह कई पंक्तियों के साथ वापस आ गया है जहां एकल event_id के लिए एकाधिक sp.payout मान हैं। – Martin

+0

@ मार्टिन: मेरा संशोधित उत्तर देखें। –