'Function that given a parameter will calculate a value from different tables using different logic
I am needing to create a view, and one of the columns in the view needs to calculate a value for the metric. The source table for a metric will be different depending on the metric_id, as will the logic for calculating the metric, although in all cases the return will always be a float. There are about 40 different metrics. Example view:
CREATE OR REPLEACE VIEW V_METRICS_MART AS
SELECT
METRIC_NAME,
REPORTING_PERIOD,
TEAM_NAME,
F_METRIC_VALUE(metric_id, reporting_period, team_id) FROM T_METRICS;
I did not want to create this as an ETL that would write the metric back to a table, as the underlying source data changes frequently, and I want the calculation to reflect the source as fresh as possible. (for performance this may be a materialized that gets built several times a day)
I could just have a huge CASE statement that does this, but as that seems difficult to maintain I was going to encapsulate each calculation into a separate function.
My question is, is there a way to quickly map function to a metric_id that is better than what I have? Ideally I don't want to have to modify the function every time there is a new metric. I was thinking something along the lines of a table that references the appropriate function, or even a table that maps a metric id to a sql statement, and a function that would run the query with the appropriate parameters. That way I could just maintain those queries on a table, instead of having to create a function for each one.
The queries that calculate the metric will use either reporting_period, or team_id, or both depending on the specific metric.
Below is my first attempt:
-- sample f_metric_value definition
CREATE OR REPLACE FUNCTION F_METRIC_VALUE(metric_id INTEGER, reporting_period DATE, team_id INTEGER)
RETURN FLOAT DETERMINISTIC IS metric_value FLOAT;
BEGIN
CASE metric_id
WHEN 1 THEN metric_value := f_metric_foo(reporting_period);
WHEN 2 THEN metric_value := f_metric_bar(reporting_period, team_id);
END CASE;
RETURN(metric_value);
END;
-- sample f_metric_foo
CREATE OR REPLACE FUNCTION f_metric_foo (reporting_period DATE)
RETURN FLOAT DETERMINISTIC IS metric_value FLOAT;
BEGIN
SELECT VALUE_1 - VALUE_2 INTO metric_value FROM T_FOO WHERE transaction_dt = reporting_period;
RETURN (metric_value);
END;
--sample f_metric_bar
CREATE OR REPLACE FUNCTION f_metric_bar (reporting_period DATE, team_id INTEGER)
RETURN FLOAT DETERMINISTIC IS metric_value FLOAT;
BEGIN
SELECT VALUE_1/VALUE_2 INTO metric_value FROM T_BAR where team = team_id and transaction_dt = reporting_period;
RETURN (metric_value);
END;
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|