उपयोग करें RETURN QUERY:
CREATE OR REPLACE FUNCTION word_frequency(_max_tokens int)
RETURNS TABLE (txt text -- also visible as OUT parameter inside function
, cnt bigint
, ratio bigint) AS
$func$
BEGIN
RETURN QUERY
SELECT t.txt
, count(*) AS cnt -- column alias only visible inside
, (count(*) * 100) / _max_tokens -- I added brackets
FROM (
SELECT t.txt
FROM token t
WHERE t.chartype = 'ALPHABETIC'
LIMIT _max_tokens
) t
GROUP BY t.txt
ORDER BY cnt DESC; -- potential ambiguity
END
$func$ LANGUAGE plpgsql;
कॉल करें:
SELECT * FROM word_frequency(123);
स्पष्टीकरण:
यह है बहुत स्पष्ट रूप से बस रिकॉर्ड के रूप में यह घोषित करने से वापसी प्रकार परिभाषित करने के लिए और अधिक व्यावहारिक। इस तरह आपको हर फ़ंक्शन कॉल के साथ एक कॉलम परिभाषा सूची प्रदान करने की आवश्यकता नहीं है। RETURNS TABLEऐसा करने का एक तरीका है। और भी हैं। डेटा प्रकार के OUTमापदंडों को ठीक उसी तरह से मेल खाना है जो क्वेरी द्वारा वापस किया गया है।
OUTमापदंडों के लिए नामों को सावधानी से चुनें । वे लगभग कहीं भी फ़ंक्शन बॉडी में दिखाई देते हैं। झगड़े या अप्रत्याशित परिणामों से बचने के लिए तालिका-समान नाम के कॉलम। मैंने अपने उदाहरण में सभी कॉलमों के लिए किया।
लेकिन पैरामीटर और उसी नाम के कॉलम उर्फ के बीच संभावित नामकरण संघर्ष पर ध्यान दें । इस विशेष मामले में ( ) Postgres पैरामीटर के ऊपर कॉलम एलियास का उपयोग करता है । यह अन्य संदर्भों में अस्पष्ट हो सकता है, हालांकि। किसी भी भ्रम से बचने के विभिन्न तरीके हैं:OUTcntRETURN QUERY SELECT ...OUT
- चयन सूची में आइटम की क्रमिक स्थिति का उपयोग करें
ORDER BY 2 DESC:। उदाहरण:
- अभिव्यक्ति को दोहराएं
ORDER BY count(*)।
- (यहां लागू नहीं है।) कॉन्फ़िगरेशन पैरामीटर सेट करें
plpgsql.variable_conflictया #variable_conflict error | use_variable | use_columnफ़ंक्शन में विशेष कमांड का उपयोग करें । देख:
कॉलम नामों के रूप में "टेक्स्ट" या "काउंट" का उपयोग न करें। दोनों Postgres में उपयोग करने के लिए कानूनी हैं, लेकिन "गणना" मानक SQL में एक आरक्षित शब्द है और एक बुनियादी फ़ंक्शन नाम और "टेक्स्ट" एक बुनियादी डेटा प्रकार है। भ्रामक त्रुटियां हो सकती हैं। मैं अपने उदाहरणों में उपयोग करता हूं txtऔर करता cntहूं।
;हेडर में एक लापता और एक वाक्यविन्यास त्रुटि को जोड़ा गया । (_max_tokens int), नहीं (int maxTokens)- नाम के बाद टाइप करें ।
पूर्णांक विभाजन के साथ काम करते समय, पहले वाली को गुणा करना और बाद में विभाजित करना, गोल त्रुटि को कम करने के लिए बेहतर है। इससे भी बेहतर: साथ काम numeric(या एक अस्थायी बिंदु प्रकार)। निचे देखो।
विकल्प
यह वही है जो मुझे लगता है कि आपकी क्वेरी वास्तव में दिखनी चाहिए ( प्रति टोकन एक रिश्तेदार शेयर की गणना ):
CREATE OR REPLACE FUNCTION word_frequency(_max_tokens int)
RETURNS TABLE (txt text
, abs_cnt bigint
, relative_share numeric) AS
$func$
BEGIN
RETURN QUERY
SELECT t.txt, t.cnt
, round((t.cnt * 100) / (sum(t.cnt) OVER ()), 2) -- AS relative_share
FROM (
SELECT t.txt, count(*) AS cnt
FROM token t
WHERE t.chartype = 'ALPHABETIC'
GROUP BY t.txt
ORDER BY cnt DESC
LIMIT _max_tokens
) t
ORDER BY t.cnt DESC;
END
$func$ LANGUAGE plpgsql;
अभिव्यक्ति sum(t.cnt) OVER ()एक विंडो फ़ंक्शन है । आप सब- वेरी के बजाय एक सीटीई का उपयोग कर सकते हैं - सुंदर, लेकिन एक उपक्वरी आम तौर पर इस तरह के सरल मामलों में सस्ता है।
मापदंडों के साथ काम करते समय या (जो मापदंडों का निहित उपयोग करता है ) एक अंतिम स्पष्ट RETURNकथन की आवश्यकता नहीं है (लेकिन अनुमति दी गई है )।OUTRETURNS TABLEOUT
round()दो मापदंडों के साथ केवल numericप्रकारों के लिए काम करता है । count()उपनगर में एक bigintपरिणाम उत्पन्न होता है और sum()इस पर bigintएक numericपरिणाम उत्पन्न होता है, इस प्रकार हम एक numericसंख्या के साथ स्वचालित रूप से व्यवहार करते हैं और सब कुछ बस जगह में गिर जाता है।