मैंने Loan नाम की एक टेबल बनाई है जिसमें निम्नलिखित कॉलम हैं:

loanID SERIAL, 
annualInterestRate INT, 
numberOfYears INT, 
loanAmount NUMERIC, 
monthlyPayment NUMERIC

monthlyPayment की गणना निम्न सूत्र के अनुसार numberOfYears, loanAmount और annualInterestRate पर निर्भर करती है:

monthlyPayment = (loanAmount * monthlyInterestRate) /
                (1 - (1/Math.pow(1 + monthlyInterestRate , numberOfYears * 12) ));

मैंने get_monthly_payment() नाम का एक फंक्शन बनाया है जो बिना किसी समस्या के monthlyPayment लौटाता है। प्रत्येक पंक्ति के लिए, मैं इस फ़ंक्शन की वापसी को कॉलम monthlyPayment का डिफ़ॉल्ट बनाना चाहता हूं। इसे कैसे प्राप्त किया जा सकता है?

3
Hussein Eid 18 जुलाई 2020, 00:23

3 जवाब

सबसे बढ़िया उत्तर

अगर monthlyPayment आपकी परिभाषा के अनुसार तय किया गया है, इसलिए पूरी तरह कार्यात्मक रूप से निर्भर है, तो मान बिल्कुल को जारी न रखने पर विचार करें। इसके बजाय अपने सस्ते (!) फ़ंक्शन का उपयोग करते रहें। कुल मिलाकर बहुत साफ और सस्ता। पसंद:

SELECT *, f_monthly_payment(l) AS monthly_payment
FROM loan l;

मान लें कि फ़ंक्शन को f_monthly_payment(loan) के रूप में परिभाषित किया गया है (तालिका के पंक्ति प्रकार को तर्क के रूप में लेते हुए)। वरना उसके हिसाब से अनुकूलन करें।

पोस्टग्रेज 12 या बाद के संस्करण में STORED जेनरेट किए गए कॉलम हैं, लेकिन वे केवल महंगी गणनाओं के लिए भुगतान करते हैं। स्थायी कॉलम स्थान घेरते हैं और टेबल पर सभी कार्यों को धीमा कर देते हैं।

देखो:

यदि आप मैन्युअल परिवर्तनों की अनुमति देना चाहते हैं, तो एक कॉलम डिफ़ॉल्ट जाने का रास्ता है (जैसे आपने वास्तव में पूछा)। लेकिन आप अपने फ़ंक्शन का उपयोग नहीं कर सकते क्योंकि, मैनुअल को उद्धृत करना:

DEFAULT क्लॉज उस कॉलम के लिए एक डिफ़ॉल्ट डेटा मान निर्दिष्ट करता है जिसका कॉलम परिभाषा यह भीतर दिखाई देती है। मान कोई चर-मुक्त है अभिव्यक्ति (विशेष रूप से, अन्य स्तंभों के लिए क्रॉस-रेफरेंस) वर्तमान तालिका की अनुमति नहीं है)।

इसके लिए शेष समाधान टेबल पर एक ट्रिगर BEFORE INSERT है जैसे:

CREATE OR REPLACE FUNCTION trg_loan_default_rate()
  RETURNS trigger
  LANGUAGE plpgsql AS
$func$
BEGIN
   NEW.monthlyPayment := (NEW.loanAmount * monthlyInterestRate())
                    / (1 - (1/power(1 + monthlyInterestRate(), NEW.numberOfYears * 12)));

   RETURN NEW;
END
$func$;

CREATE TRIGGER loan_default_rate
BEFORE INSERT ON loan
FOR EACH ROW EXECUTE FUNCTION trg_loan_default_rate();

मान लें कि monthlyInterestRate() एक कस्टम फ़ंक्शन है।
और मैंने Math.pow को बिल्ट-इन पोस्टग्रेज़ फ़ंक्शन power()

NEW ट्रिगर फ़ंक्शंस में एक विशेष रिकॉर्ड चर है, जो नई सम्मिलित पंक्ति को संदर्भित करता है। देखो:

EXECUTE FUNCTION को पोस्टग्रेज 11 की आवश्यकता है। देखें:

सम्बंधित:

इसके अलावा: पोस्टग्रेज में कानूनी, लोअर-केस, गैर-उद्धृत पहचानकर्ताओं पर विचार करें। ले देख:

1
Erwin Brandstetter 18 जुलाई 2020, 03:33

पोस्टग्रेज 12+ में आपने कॉलम जेनरेट किए हैं:

एक उत्पन्न कॉलम एक विशेष कॉलम होता है जिसे हमेशा अन्य कॉलम से गणना की जाती है।

"एक जेनरेट किया गया कॉलम एक विशेष कॉलम होता है जिसे हमेशा अन्य कॉलम से गणना की जाती है। ..."

इसलिए:

monthlyPayment numeric GENERATED ALWAYS AS(loanAmount * monthlyInterestRate) /
                (1 - (1/Math.pow(1 + monthlyInterestRate , numberOfYears * 12) ))  STORED

संस्करण 12 से पहले आपको तालिका में एक ट्रिगर जोड़ने के लिए CREATE TRIGGER का उपयोग करना होगा जो उपरोक्त समीकरण वाले फ़ंक्शन को कॉल करता है और कॉलम मान सेट करता है।

0
Adrian Klaver 18 जुलाई 2020, 01:18

मासिक ब्याज दर आपकी टेबल पर कॉलम नहीं हो सकती है, लेकिन वार्षिक दर है। लेकिन वार्षिक से मासिक एक साधारण गणना है। ट्रिगर का उपयोग करके v12 जेनरेट किए गए कॉलम और पिछले संस्करणों दोनों के लिए निम्नलिखित का उपयोग किया जा सकता है। इसके अतिरिक्त यह मासिक भुगतान गणना के लिए आम तौर पर उपयोगी पोस्टग्रेस फ़ंक्शन प्रदान करता है। प्रत्येक के लिए fiddle देखें।

create or replace 
function monthly_loan_payment 
       ( amount  numeric
       , apr     numeric
       , term    numeric
       )
  returns numeric
  language sql 
  immutable strict  
/*  Given a loan amount, the Annual Percent (Interest) Rate and term (in years) 
 *  compute the monthly payment to service the loan. 
 *  Note. Monthly payment calculates correctly, but due to the exact terms of loan
 *        and date of payment receipt adjustments for end of loan payment may be 
 *        required.  
 */ 
as $$   
  with monthly (mrate) as (values ( (apr/100.00) / 12.00 ) )
  select round((amount * mrate)  /(1.0 - (1.0/ ((1.0 +mrate)^( term * 12.00)) ))::numeric,2) 
     from monthly;
$$; 
0
Belayer 18 जुलाई 2020, 03:40