Still kinda new to PL/SQL but basically I'm trying to create a function that will calculate a person's score depending on how much money they've paid in the last 8 years. It uses the sums for each year for calculations. The formula is (Year-1)/Year-2) * (Year-2/Year-3) * (Year3/Year4) and so on. What makes it extra tricky is that I need to skip years where they gave 0.
For example:
Here's the code I have so far:
CREATE OR REPLACE FUNCTION formula
(idnum IN NUMBER)
RETURN NUMBER IS score NUMBER;
-- Declare Variables
currentyear NUMBER := EXTRACT (YEAR FROM SYSDATE);
previousyear NUMBER := currentyear - 1;
yeareight NUMBER := currentyear - 8;
previoussum NUMBER := 0;
currentsum NUMBER := 0;
placeholder NUMBER := 0;
score NUMBER := 1;
BEGIN
-- Set Score to 0 if no history of payments in the last 8 years
SELECT NVL(SUM(amount), 0)
INTO currentsum
FROM moneytable g
WHERE g.id_number = idnum
AND g.fiscal_year BETWEEN yeareight AND previousyear;
IF currentsum = 0 THEN score := 0;
ELSE
-- Loop to calculate Score
-- Score formula is (Year-1/Year -2) * (Year-2/Year-3) and so on for the last 8 years
-- Zeroes ignored for above calculations
-- Score defaults to 1 if only one year has any gifts
FOR counter IN 1..8
LOOP
currentyear := currentyear - 1;
placeholder := 0;
SELECT NVL(SUM(amount), 0)
INTO currentsum
FROM moneytable g
WHERE g.id_number = idnum
AND g.fiscal_year = currentyear;
IF currentsum = 0 THEN CONTINUE;
ELSE placeholder := previoussum / currentsum; END IF;
previoussum := currentsum;
IF currentsum > 0 AND placeholder > 0 THEN score := score * placeholder; END IF;
END LOOP;
END IF;
RETURN score;
END;
It works and it gives the correct score but it runs super slow if I try running it more for than a few people at a time. Is there a more efficient, optimized way to create this function?