11

के प्रतिशत की गणना करने के लिए SQL विंडो फ़ंक्शन का उपयोग कैसे करें मुझे तालिका में विभिन्न आयामों के प्रतिशत की गणना करने की आवश्यकता है। मैं denominator की गणना करने के लिए विंडो कार्यों का उपयोग करके चीजों को सरल बनाना चाहता हूं, हालांकि मुझे कोई समस्या है क्योंकि संख्यात्मक को भी कुल मिलाकर होना चाहिए।कुल

एक साधारण उदाहरण के रूप में, निम्न तालिका ले:

create temp table test (d1 text, d2 text, v numeric); 
insert into test values ('a','x',5), ('a','y',5), ('a','y',10), ('b','x',20); 

मैं सिर्फ d1 से बाहर प्रत्येक व्यक्ति पंक्ति के शेयर की गणना करना चाहते हैं, तो विंडोइंग कार्यों ठीक से काम:

select d1, d2, v/sum(v) over (partition by d1) 
from test; 

"b";"x";1.00 
"a";"x";0.25 
"a";"y";0.25 
"a";"y";0.50 

हालांकि, मुझे क्या करना है डी 1 के बाहर डी 2 के योग के लिए कुल शेयर की गणना करना है।

select d1, d2, sum(v)/sum(v) over (partition by d1) 
from test 
group by d1, d2; 

हालांकि, अब मैं कोई त्रुटि मिलती है:

"b";"x";1.00 
"a";"x";0.25 
"a";"y";0.75 

तो मैं इस प्रयास करें:

ERROR: column "test.v" must appear in the GROUP BY clause or be used in an aggregate function 

मैं इस वजह से है यह सोचते हैं रहा हूँ उत्पादन मैं देख रहा हूँ यह है यह शिकायत कर रहा है कि समूह फ़ंक्शन को समूहबद्ध खंड में नहीं माना जाता है, हालांकि विंडोिंग फ़ंक्शंस को समूहबद्ध खंड में भी नहीं रखा जा सकता है।

यह ग्रीनप्लम 4.1 का उपयोग कर रहा है, जो पोस्टग्रेस्क्ल 8.4 का कांटा है और उसी विंडोिंग फ़ंक्शन साझा करता है। ध्यान दें कि ग्रीनप्लम सहसंबंधित सबक्वायरी नहीं कर सकता है।

उत्तर

16

मुझे लगता है कि क्या आप वास्तव में देख रहे है :

SELECT d1, d2, sum(v)/sum(sum(v)) OVER (PARTITION BY d1) AS share 
FROM test 
GROUP BY d1, d2; 

अनुरोधित परिणाम उत्पन्न करता है।

विंडो फ़ंक्शन कुल कार्यों के बाद लागू होते हैं। sum(sum(v)) में इस उदाहरण में एक विंडो फ़ंक्शन है और OVER ... खंड से जुड़ा हुआ है, जबकि आंतरिक sum() कुल है।

प्रभावी ढंग से एक ही रूप में:

WITH x AS (
    SELECT d1, d2, sum(v) AS sv 
    FROM test 
    GROUP BY d1, d2 
    ) 
SELECT d1, d2, sv/sum(sv) OVER (PARTITION BY d1) AS share 
FROM x; 

या (CTE के बिना):

SELECT d1, d2, sv/sum(sv) OVER (PARTITION BY d1) AS share 
FROM (
    SELECT d1, d2, sum(v) AS sv 
    FROM test 
    GROUP BY d1, d2 
    ) x; 

या @ म्यू के संस्करण।

इसके अलावा: ग्रीनप्लम ने संस्करण 4.2 के साथ सहसंबंधित सबक्वायर पेश किए। See release notes.

+0

आह महान! यही वह था जो मैं बाद में था। समझ में आता है। दस्तावेज़ इस सामान पर स्पष्ट नहीं हैं। – EvilPuppetMaster

+0

@erwinbrandsletter ने अपना जीवन बचाया! धन्यवाद – isJustMe

1

क्या आपको इसे विंडो कार्यों के साथ करने की ज़रूरत है? लगता है कि आप सिर्फ समूह के लिए परिणाम की जरूरत है आप d1 और d2 से है और उसके बाद रकम का योग:

select d1, d2, sum(p) 
from (
    select d1, d2, v/sum(v) over (partition by d1) as p 
    from test 
) as dt 
group by d1, d2 

जो मुझे देता है यह:

d1 | d2 |   sum   
----+----+------------------------ 
a | x | 0.25000000000000000000 
a | y | 0.75000000000000000000 
b | x | 1.00000000000000000000 
+1

आह सच है, जो वास्तव में काम करता है। कारण मैं उप-प्रश्न के बिना इसे करना चाहता हूं क्योंकि यह वास्तव में एक बीआई उपकरण (टेबलू) में जाना है, और सबक्वायरी मुद्दों का कारण बनता है। – EvilPuppetMaster

संबंधित मुद्दे