PostgreSQL এ কোনও ফাংশনের অভ্যন্তরে একটি নির্বাচন ফলাফল কীভাবে ফিরে আসবে?


106

পোস্টগ্রেএসকিউএল-এ আমার এই ফাংশন রয়েছে তবে কোয়েরির ফলাফল কীভাবে ফিরে আসতে হবে তা আমি জানি না:

CREATE OR REPLACE FUNCTION wordFrequency(maxTokens INTEGER)
  RETURNS SETOF RECORD AS
$$
BEGIN
    SELECT text, count(*), 100 / maxTokens * count(*)
    FROM (
        SELECT text
    FROM token
    WHERE chartype = 'ALPHABETIC'
    LIMIT maxTokens
    ) as tokens
    GROUP BY text
    ORDER BY count DESC
END
$$
LANGUAGE plpgsql;

কিন্তু আমি জানি না কীভাবে পোস্টগ্রিজ এসকিউএল ফাংশনের অভ্যন্তরে ক্যোয়ারির ফলাফলটি ফিরে আসবে।

আমি খুঁজে পেয়েছি যে রিটার্ন টাইপ হওয়া উচিত SETOF RECORD, তাই না? তবে রিটার্ন কমান্ড ঠিক নেই।

এটি করার সঠিক উপায় কী?


কেন আপনি তাদের গণনা; আপনার টোকেন টেবিলটিতে নকল টোকেন রয়েছে? এছাড়াও: দয়া করে আপনার প্রশ্নের সারণী সংজ্ঞা যুক্ত করুন।
ওয়াইল্ডপ্লেজার

1
এটি কি আপনার সম্পূর্ণ ফাংশন? যদি ফাংশনে আপনার অন্য কোনও বিবৃতি না থাকে তবে আপনার এটি করা উচিত LANGUAGE SQL
jpmc26

উত্তর:


134

ব্যবহার 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প্যারামিটারগুলির জন্য নামগুলি সাবধানে চয়ন করুন। এগুলি ফাংশন বডিটিতে প্রায় কোথাও দৃশ্যমান। দ্বন্দ্ব বা অপ্রত্যাশিত ফলাফল এড়াতে একই নামের কলামগুলি সারণী-যোগ্য করে তোলা। আমি আমার উদাহরণে সমস্ত কলামের জন্য এটি করেছি।

    তবে প্যারামিটার এবং একই নামের কলামের নামের মধ্যে সম্ভাব্য নামকরণ বিরোধটি নোট করুন । এই বিশেষ ক্ষেত্রে ( ) পোস্টগ্র্যাসগুলি প্যারামিটারের উপর দিয়ে কলামের নাম ব্যবহার করে । যদিও অন্যান্য প্রসঙ্গে এটি অস্পষ্ট হতে পারে। কোনও বিভ্রান্তি এড়াতে বিভিন্ন উপায় রয়েছে:OUTcntRETURN QUERY SELECT ...OUT

    1. নির্বাচন তালিকায় আইটেমের পূরণবাচক অবস্থান ব্যবহার করুন: ORDER BY 2 DESC। উদাহরণ:
    2. এক্সপ্রেশন পুনরাবৃত্তি ORDER BY count(*)
    3. (এখানে প্রযোজ্য নয়) কনফিগারেশন প্যারামিটার সেট করুন plpgsql.variable_conflictবা #variable_conflict error | use_variable | use_columnফাংশনে বিশেষ কমান্ডটি ব্যবহার করুন । দেখা:
  • কলামের নাম হিসাবে "পাঠ্য" বা "গণনা" ব্যবহার করবেন না। উভয়ই পোস্টগ্র্রেসে ব্যবহার করার জন্য বৈধ, তবে "গণনা" স্ট্যান্ডার্ড এসকিউএল-তে একটি সংরক্ষিত শব্দ এবং একটি মৌলিক ফাংশন নাম এবং "পাঠ্য" একটি বুনিয়াদি ডেটা টাইপ। বিভ্রান্তিকর ত্রুটি হতে পারে। আমি txtএবং cntআমার উদাহরণগুলিতে ব্যবহার করি।

  • শিরোনামটিতে একটি অনুপস্থিত ;এবং সংশ্লেষের ত্রুটি যুক্ত হয়েছে। (_max_tokens int), নয় (int maxTokens)- নামের পরে টাইপ করুন

  • পূর্ণসংখ্যা বিভাগের সাথে কাজ করার সময়, গোলাকার ত্রুটিটি হ্রাস করতে প্রথমে গুণ করা এবং পরে ভাগ করা ভাল better আরও ভাল: 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 ()একটি উইন্ডো ফাংশন । আপনি সাবকোয়ারির পরিবর্তে একটি সিটিই ব্যবহার করতে পারেন - সুন্দর, তবে একটি সাবকোয়ারি সাধারণত এর মতো সাধারণ ক্ষেত্রে সস্তা che

পরামিতিগুলির সাথে কাজ করার সময় বা (যা পরামিতিগুলির অন্তর্নিহিত ব্যবহার করে ) একটি চূড়ান্ত সুস্পষ্ট RETURNবিবৃতি আবশ্যক নয় (তবে অনুমোদিত )।OUTRETURNS TABLEOUT

round()দুটি পরামিতি শুধুমাত্র numericধরণের জন্য কাজ করে । count()মধ্যে subquery একটি উত্পাদন করে bigintফলাফলের এবং sum()এই উপর bigintএকটি উত্পাদন করে numericফলে, এইভাবে আমরা সাথে মোকাবিলা numericস্বয়ংক্রিয়ভাবে নম্বর এবং সমস্তকিছু ঠিকঠাক জায়গা মধ্যে পড়ে।


আপনার উত্তর এবং সংশোধন করার জন্য খুব ধন্যবাদ। এখন ঠিকঠাক কাজ করছে (আমি কেবল অনুপাতের ধরণটিকে সংখ্যায় পরিবর্তিত করেছি)।
রেনাতো দিনহানি

নিবন্ধন করুন আমি এমন একটি সংস্করণ যুক্ত করেছি যা আপনি অতিরিক্ত জিজ্ঞাসা না করে এমন অতিরিক্ত প্রশ্নের উত্তর দিতে পারে বা নাও করতে পারে। ;)
এরউন ব্র্যান্ডসটেটার

খুব ভাল, কেবলমাত্র আমি মনে করি এর RETURN;আগে আপনার একটি প্রয়োজন হওয়া দরকার END;, কমপক্ষে আমি করেছিলাম - তবে আমি একটি ইউনিয়ন করছি তাই আমি নিশ্চিত নই যে এটি আলাদা করে তোলে কিনা।
ইয়েকটা

@ আইকতা: এর ভূমিকা সম্পর্কে আমি কিছু তথ্য যুক্ত করেছি RETURN। একটি সম্পর্কযুক্ত ত্রুটি সংশোধন করে এবং এটি থাকা অবস্থায় কিছু উন্নতি যুক্ত করেছে।
এরউইন ব্র্যান্ডসটেটার

1
রিটার্ন টেবিল () এ যা আছে তা সীমাবদ্ধ রাখতে না চাইলে এটি করার উপায় কী। IE রিটার্ন টেবিল (*)?
নিক

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.