0

I have a custom function which is supposed to calculate upper and lower quartiles. I want to compute it in a following way:

SELECT QUARTILE_UTILS.GET_QUARTILE(0.25, YEAR_1_FTE),  
       QUARTILE_UTILS.GET_QUARTILE(0.75, YEAR_1_FTE)
FROM SOME_TABLE WHERE FIRM_ID=999;

So it looks like an aggregate function. It receives a number to calculate a quartule(.25 or .75) and a collection of numbers. So here is the function body:

create or replace PACKAGE BODY QUARTILE_UTILS AS
  FUNCTION GET_QUARTILE(PERCENTILE NUMBER, DATASET NUMBERS_ARRAY) RETURN NUMBER
  IS
    REMINDER NUMBER := 0;
    I SIMPLE_INTEGER := 0;
    RESULT NUMBER := 0;
  BEGIN
    ....
    RETURN RESULT;
  END;
END QUARTILE_UTILS;

And as you can see, I defined a custom data type. Here it is:

create or replace TYPE NUMBERS_ARRAY AS TABLE OF NUMBER;

However, it still doens't work. When I try to execute I receive such error:

PLS-306: wrong number or types of arguments in call to 'GET_QUARTILE'

As far, as I understand my definition of collection of number is incorrect. What I am doing wrong?

2
  • What data type is YEAR_1_FTE? Presumably not a nested table type. You want to aggregate over all the values from the table - I think - so are you trying to write a user-defined aggregate function? Or do you want to turn the values from the table into a collection and pass that to your current function? Commented Jun 17, 2016 at 12:14
  • @AlexPoole YEAR_1_FTE is just a number. So yes, I just need to pass a collection of numbers. Commented Jun 17, 2016 at 12:15

2 Answers 2

1

Your function is expecting a collection, not a simple number; so you can use the COLLECT() function and cast what that produces to the expected table type:

SELECT QUARTILE_UTILS.GET_QUARTILE(0.25, CAST(COLLECT(YEAR_1_FTE) AS NUMBERS_ARRAY)),
       QUARTILE_UTILS.GET_QUARTILE(0.75, CAST(COLLECT(YEAR_1_FTE) AS NUMBERS_ARRAY))
FROM SOME_TABLE WHERE FIRM_ID=999;

You might want to investigate user-defined aggregate functions as an alternative though.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for your answer. I saw this article about user-defined aggregate functions. I saw, that I should develop custom data type. For me it's just looks wierd that I should perform all these steps just to pass an array of integers.
You have to create an array of integers from the individual numbers in each row. That doesn't seem unreasonable.
0

I know that my answer is offtopic . But maybe it helps you.

with abc as (select 1 lp from dual
                union all
                select 2 from dual
                union all
                select 4 from dual
                union all
                select 5 from dual
                union all
                select 8 from dual
                union all
                select 9 from dual
                union all
                select 10 from dual
                union all
             select 12 from dual)
select median(case when quartiles =1 then lp else null end), /* .25 */
       median(case when quartiles =3 then lp else null end) /* .75 */
from
( 
select 
       lp, ntile(4) over(order by lp) quartiles
from abc
)

Oracle also has PERCENTILE_DISC,PERCENTILE_CONT analytic/aggregation function.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.