BS2012 wrote:
Hi Everyone,
As we know sum is a predefined oracle function. But what these oracle guys have used for the input parameters. How they have done this?
I mean we can write this sum fuction like so many ways like as mentioned below. Please give me some ideas how to do that.
SELECT SUM(salary) as "Total Salary" FROM employees;
SELECT SUM(DISTINCT salary) as "Total Salary" FROM employees;
SELECT SUM(income - expenses) as "Net Income" FROM gl_transactions;
SELECT SUM(sales * 0.10) as "Commission" FROM order_details;
Regards,
BS2012
As others have said, your question is not quite clear.
There are many aspects and angles to looking at what you are asking.
Primarily, from a top-level, the sum function simply takes a number value as it's argument, so all those examples you have given have expressions in them that evaluate to a numeric value before being supplied to the sum function. (As someone else already mentioned you can have non-numeric datatypes, just so long as they can implicitly be converted to a numeric value).
From a statement parsing and execution perspective, the contents of the expression inside the brackets will be evaluated
before being passed to the sum function. It is not the sum function that itself takes the expression and evaluates it. The sum function just expects a single numeric value.
Internally, what the sum function does, is more than just a single... call function and return value, because it has to deal with multiple values being passed in as part of the aggregating group. As such, it needs to have the ability to know when to start it's summing, to accept multiple values as input so it can sum them together, and to know when to stop summing inputs and pass the result back.
If we write our own user defined aggregate function (other people have already provided a link to explain such) we can see what is happening internally. In this following example, we'll write a user defined function that multiplies the values rather than sums them...
create or replace type mul_type as object(
val number,
static function ODCIAggregateInitialize(sctx in out mul_type) return number,
member function ODCIAggregateIterate(self in out mul_type, value in number) return number,
member function ODCIAggregateTerminate(self in mul_type, returnvalue out number, flags in number) return number,
member function ODCIAggregateMerge(self in out mul_type, ctx2 in mul_type) return number
);
/
create or replace type body mul_type is
static function ODCIAggregateInitialize(sctx in out mul_type) return number is
begin
sctx := mul_type(null);
return ODCIConst.Success;
end;
member function ODCIAggregateIterate(self in out mul_type, value in number) return number is
begin
self.val := nvl(self.val,1) * value;
return ODCIConst.Success;
end;
member function ODCIAggregateTerminate(self in mul_type, returnvalue out number, flags in number) return number is
begin
returnValue := self.val;
return ODCIConst.Success;
end;
member function ODCIAggregateMerge(self in out mul_type, ctx2 in mul_type) return number is
begin
self.val := self.val * ctx2.val;
return ODCIConst.Success;
end;
end;
/
create or replace function mul(input number) return number deterministic parallel_enable aggregate using mul_type;
/
So, our user defined aggregate function is based on an aggregate object type.
This object holds a value ("val" in our example).
It has an Initialize method, so when the SQL engine indicates that it's the start of an aggregation of values it can set it's value to an initial value (in this case null).
It has an Iterate method, so as the SQL engine passes values to it as part of the aggregated set of values, it can process them (in our case it multiplies the input value with the value it already has for this set of aggregations (and takes a base value of 1 for the first iteration))
It has a Terminate method, so when the SQL engine indicates that the aggregate set of values is complete, it can return the result.
The last method in there is a Merge and is a mandatory requirement, so that when aggregation is done using parallel evaluation (to improve performance internally), the results of those parallelly executed aggregations can be combined together (see http://docs.oracle.com/cd/E11882_01/appdev.112/e10765/ext_agg_ref.htm#ADDCI5132). As we're multiplying numbers, in our case, it is simply a case of multiplying one result with the other.
And to see it working...
SQL> with t as (select 2 as x from dual union all
2 select 3 from dual union all
3 select 4 from dual union all
4 select 5 from dual)
5 --
6 select mul(x)
7 from t;
MUL(X)
----------
120