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)
LANGUAGE plpgsql 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$;
कॉल करें:
SELECT * FROM word_frequency(123);
वापसी प्रकार को स्पष्ट रूप से परिभाषित करना बहुत है सामान्य record
returning लौटाने से अधिक व्यावहारिक . इस तरह आपको प्रत्येक फ़ंक्शन कॉल के साथ कॉलम परिभाषा सूची प्रदान करने की आवश्यकता नहीं है। RETURNS TABLE
ऐसा करने का एक तरीका है। अन्य हैं। डेटा प्रकार OUT
पैरामीटर को ठीक उसी तरह मेल खाना चाहिए जो क्वेरी द्वारा लौटाया जाता है।
OUT
. के लिए नाम चुनें पैरामीटर सावधानी से। वे फंक्शन बॉडी में लगभग कहीं भी दिखाई देते हैं। विरोध या अनपेक्षित परिणामों से बचने के लिए समान नाम के तालिका-योग्य स्तंभ। मैंने अपने उदाहरण के सभी स्तंभों के लिए ऐसा किया है।
लेकिन संभावित नामकरण विरोध पर ध्यान दें OUT
. के बीच पैरामीटर cnt
और इसी नाम का स्तंभ उपनाम। इस विशेष मामले में (RETURN QUERY SELECT ...
) पोस्टग्रेज OUT
. के ऊपर कॉलम एलियास का उपयोग करता है किसी भी तरह से पैरामीटर। हालांकि यह अन्य संदर्भों में अस्पष्ट हो सकता है। किसी भी भ्रम से बचने के कई तरीके हैं:
- चयन सूची में आइटम की क्रमिक स्थिति का उपयोग करें:
ORDER BY 2 DESC
. उदाहरण:- समूह द्वारा प्रत्येक समूह में पहली पंक्ति का चयन करें?
- अभिव्यक्ति को दोहराएं
ORDER BY count(*)
। - (यहां लागू नहीं है।) कॉन्फ़िगरेशन पैरामीटर सेट करें
plpgsql.variable_conflict
या विशेष कमांड का उपयोग करें#variable_conflict error | use_variable | use_column
समारोह में। देखें:- फ़ंक्शन पैरामीटर और USING क्लॉज़ के साथ JOIN के परिणाम के बीच विरोध का नामकरण
कॉलम नामों के रूप में "पाठ" या "गिनती" का प्रयोग न करें। दोनों पोस्टग्रेज में उपयोग करने के लिए कानूनी हैं, लेकिन "गिनती" एक आरक्षित शब्द . है मानक 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)
LANGUAGE plpgsql 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$;
व्यंजक sum(t.cnt) OVER ()
एक विंडो फ़ंक्शन है। आप कर सकते थे सबक्वायरी के बजाय सीटीई का प्रयोग करें। सुंदर, लेकिन इस तरह के साधारण मामलों में एक सबक्वेरी आमतौर पर सस्ता होता है (ज्यादातर पोस्टग्रेज 12 से पहले)।
एक अंतिम स्पष्ट RETURN
कथन नहीं है OUT
. के साथ काम करते समय आवश्यक (लेकिन अनुमति) पैरामीटर या RETURNS TABLE
(जो OUT
. का निहित उपयोग करता है पैरामीटर)।
round()
केवल दो पैरामीटर के साथ numeric
. के लिए काम करता है प्रकार। count()
सबक्वेरी में एक bigint
पैदा करता है परिणाम और एक sum()
इस पर bigint
एक numeric
उत्पन्न करता है परिणाम, इस प्रकार हम एक numeric
. से निपटते हैं नंबर अपने आप आ जाता है और सब कुछ ठीक हो जाता है।