[ TOC ]
[ Previous ]
[ Next ]
10. EXTENDING SQL: AGGREGATES
Aggregates in POSTGRES are expressed in terms of state
transition functions. That is, an aggregate can be
defined in terms of state that is modified whenever an
instance is processed. Some state functions look at a
particular value in the instance when computing the new
state (sfunc1 in the create aggregate syntax) while
others only keep track of their own internal state
(sfunc2).
If we define an aggregate that uses only sfunc1, we
define an aggregate that computes a running function of
the attribute values from each instance. "Sum" is an
example of this kind of aggregate. "Sum" starts at
zero and always adds the current instance's value to
its running total. We will use the int4pl that is
built into POSTGRES to perform this addition.
CREATE AGGREGATE complex_sum (
sfunc1 = complex_add,
basetype = complex,
stype1 = complex,
initcond1 = '(0,0)'
);
SELECT complex_sum(a) FROM test_complex;
+------------+
|complex_sum |
+------------+
|(34,53.9) |
+------------+
If we define only sfunc2, we are specifying an aggregate
that computes a running function that is independent of
the attribute values from each instance.
"Count" is the most common example of this kind of
aggregate. "Count" starts at zero and adds one to its
running total for each instance, ignoring the instance
value. Here, we use the built-in int4inc routine to do
the work for us. This routine increments (adds one to)
its argument.
CREATE AGGREGATE my_count (sfunc2 = int4inc, -- add one
basetype = int4, stype2 = int4,
initcond2 = '0')
SELECT my_count(*) as emp_count from EMP;
+----------+
|emp_count |
+----------+
|5 |
+----------+
"Average" is an example of an aggregate that requires
both a function to compute the running sum and a function
to compute the running count. When all of the
instances have been processed, the final answer for the
aggregate is the running sum divided by the running
count. We use the int4pl and int4inc routines we used
before as well as the POSTGRES integer division
routine, int4div, to compute the division of the sum by
the count.
CREATE AGGREGATE my_average (sfunc1 = int4pl, -- sum
basetype = int4,
stype1 = int4,
sfunc2 = int4inc, -- count
stype2 = int4,
finalfunc = int4div, -- division
initcond1 = '0',
initcond2 = '0')
SELECT my_average(salary) as emp_average FROM EMP;
+------------+
|emp_average |
+------------+
|1640 |
+------------+
[ TOC ]
[ Previous ]
[ Next ]