2010-09-20 22:08:53 +02:00
|
|
|
<!-- doc/src/sgml/xaggr.sgml -->
|
2000-03-31 05:27:42 +02:00
|
|
|
|
2003-04-10 03:22:45 +02:00
|
|
|
<sect1 id="xaggr">
|
2011-02-01 23:00:26 +01:00
|
|
|
<title>User-defined Aggregates</title>
|
1998-03-01 09:16:16 +01:00
|
|
|
|
2001-05-13 00:51:36 +02:00
|
|
|
<indexterm zone="xaggr">
|
2003-08-31 19:32:24 +02:00
|
|
|
<primary>aggregate function</primary>
|
|
|
|
<secondary>user-defined</secondary>
|
2001-05-13 00:51:36 +02:00
|
|
|
</indexterm>
|
|
|
|
|
2000-03-30 07:07:48 +02:00
|
|
|
<para>
|
2008-11-20 22:10:44 +01:00
|
|
|
Aggregate functions in <productname>PostgreSQL</productname>
|
2006-07-27 21:52:07 +02:00
|
|
|
are expressed in terms of <firstterm>state values</firstterm>
|
2000-03-30 07:07:48 +02:00
|
|
|
and <firstterm>state transition functions</firstterm>.
|
2006-07-27 21:52:07 +02:00
|
|
|
That is, an aggregate operates using a state value that is updated
|
|
|
|
as each successive input row is processed.
|
|
|
|
To define a new aggregate
|
2001-09-10 23:58:47 +02:00
|
|
|
function, one selects a data type for the state value,
|
2000-03-30 07:07:48 +02:00
|
|
|
an initial value for the state, and a state transition
|
|
|
|
function. The state transition function is just an
|
|
|
|
ordinary function that could also be used outside the
|
2000-07-17 05:05:41 +02:00
|
|
|
context of the aggregate. A <firstterm>final function</firstterm>
|
2003-04-10 03:22:45 +02:00
|
|
|
can also be specified, in case the desired result of the aggregate
|
2000-07-17 05:05:41 +02:00
|
|
|
is different from the data that needs to be kept in the running
|
|
|
|
state value.
|
2000-03-30 07:07:48 +02:00
|
|
|
</para>
|
2000-03-26 21:45:21 +02:00
|
|
|
|
2000-03-30 07:07:48 +02:00
|
|
|
<para>
|
2003-04-10 03:22:45 +02:00
|
|
|
Thus, in addition to the argument and result data types seen by a user
|
2001-09-10 23:58:47 +02:00
|
|
|
of the aggregate, there is an internal state-value data type that
|
Update documentation on may/can/might:
Standard English uses "may", "can", and "might" in different ways:
may - permission, "You may borrow my rake."
can - ability, "I can lift that log."
might - possibility, "It might rain today."
Unfortunately, in conversational English, their use is often mixed, as
in, "You may use this variable to do X", when in fact, "can" is a better
choice. Similarly, "It may crash" is better stated, "It might crash".
Also update two error messages mentioned in the documenation to match.
2007-01-31 21:56:20 +01:00
|
|
|
might be different from both the argument and result types.
|
2000-03-30 07:07:48 +02:00
|
|
|
</para>
|
2000-03-26 21:45:21 +02:00
|
|
|
|
2000-03-30 07:07:48 +02:00
|
|
|
<para>
|
2000-07-17 05:05:41 +02:00
|
|
|
If we define an aggregate that does not use a final function,
|
2000-03-30 07:07:48 +02:00
|
|
|
we have an aggregate that computes a running function of
|
2003-04-10 03:22:45 +02:00
|
|
|
the column values from each row. <function>sum</> is an
|
|
|
|
example of this kind of aggregate. <function>sum</> starts at
|
2001-01-14 00:58:55 +01:00
|
|
|
zero and always adds the current row's value to
|
2002-01-07 03:29:15 +01:00
|
|
|
its running total. For example, if we want to make a <function>sum</>
|
2001-09-10 23:58:47 +02:00
|
|
|
aggregate to work on a data type for complex numbers,
|
|
|
|
we only need the addition function for that data type.
|
2003-04-10 03:22:45 +02:00
|
|
|
The aggregate definition would be:
|
2008-11-20 22:10:44 +01:00
|
|
|
|
2003-04-10 03:22:45 +02:00
|
|
|
<screen>
|
2006-04-15 19:45:46 +02:00
|
|
|
CREATE AGGREGATE sum (complex)
|
|
|
|
(
|
2000-07-17 05:05:41 +02:00
|
|
|
sfunc = complex_add,
|
|
|
|
stype = complex,
|
|
|
|
initcond = '(0,0)'
|
1998-10-30 20:37:19 +01:00
|
|
|
);
|
1998-03-01 09:16:16 +01:00
|
|
|
|
2006-04-15 19:45:46 +02:00
|
|
|
SELECT sum(a) FROM test_complex;
|
1998-03-01 09:16:16 +01:00
|
|
|
|
2006-04-15 19:45:46 +02:00
|
|
|
sum
|
|
|
|
-----------
|
2002-01-07 03:29:15 +01:00
|
|
|
(34,53.9)
|
|
|
|
</screen>
|
2000-03-26 21:45:21 +02:00
|
|
|
|
2006-04-15 19:45:46 +02:00
|
|
|
(Notice that we are relying on function overloading: there is more than
|
|
|
|
one aggregate named <function>sum</>, but
|
|
|
|
<productname>PostgreSQL</productname> can figure out which kind
|
|
|
|
of sum applies to a column of type <type>complex</type>.)
|
2000-03-30 07:07:48 +02:00
|
|
|
</para>
|
1998-03-01 09:16:16 +01:00
|
|
|
|
2000-03-30 07:07:48 +02:00
|
|
|
<para>
|
2002-01-07 03:29:15 +01:00
|
|
|
The above definition of <function>sum</function> will return zero (the initial
|
2003-04-10 03:22:45 +02:00
|
|
|
state condition) if there are no nonnull input values.
|
2004-11-15 07:32:15 +01:00
|
|
|
Perhaps we want to return null in that case instead — the SQL standard
|
2002-01-07 03:29:15 +01:00
|
|
|
expects <function>sum</function> to behave that way. We can do this simply by
|
2001-09-10 23:58:47 +02:00
|
|
|
omitting the <literal>initcond</literal> phrase, so that the initial state
|
2003-04-10 03:22:45 +02:00
|
|
|
condition is null. Ordinarily this would mean that the <literal>sfunc</literal>
|
2011-03-23 21:56:55 +01:00
|
|
|
would need to check for a null state-condition input. But for
|
2003-08-10 00:50:22 +02:00
|
|
|
<function>sum</function> and some other simple aggregates like
|
|
|
|
<function>max</> and <function>min</>,
|
|
|
|
it is sufficient to insert the first nonnull input value into
|
2000-07-17 05:05:41 +02:00
|
|
|
the state variable and then start applying the transition function
|
2003-04-10 03:22:45 +02:00
|
|
|
at the second nonnull input value. <productname>PostgreSQL</productname>
|
|
|
|
will do that automatically if the initial condition is null and
|
2001-09-13 17:55:24 +02:00
|
|
|
the transition function is marked <quote>strict</> (i.e., not to be called
|
2003-04-10 03:22:45 +02:00
|
|
|
for null inputs).
|
2000-03-30 07:07:48 +02:00
|
|
|
</para>
|
2008-11-20 22:10:44 +01:00
|
|
|
|
2000-03-30 07:07:48 +02:00
|
|
|
<para>
|
2001-09-13 17:55:24 +02:00
|
|
|
Another bit of default behavior for a <quote>strict</> transition function
|
2000-07-17 05:05:41 +02:00
|
|
|
is that the previous state value is retained unchanged whenever a
|
2003-04-10 03:22:45 +02:00
|
|
|
null input value is encountered. Thus, null values are ignored. If you
|
2006-07-27 21:52:07 +02:00
|
|
|
need some other behavior for null inputs, do not declare your
|
|
|
|
transition function as strict; instead code it to test for null inputs and
|
|
|
|
do whatever is needed.
|
2000-07-17 05:05:41 +02:00
|
|
|
</para>
|
2008-11-20 22:10:44 +01:00
|
|
|
|
2000-07-17 05:05:41 +02:00
|
|
|
<para>
|
2006-07-27 21:52:07 +02:00
|
|
|
<function>avg</> (average) is a more complex example of an aggregate.
|
|
|
|
It requires
|
2000-07-17 05:05:41 +02:00
|
|
|
two pieces of running state: the sum of the inputs and the count
|
|
|
|
of the number of inputs. The final result is obtained by dividing
|
2011-03-23 21:56:55 +01:00
|
|
|
these quantities. Average is typically implemented by using an
|
|
|
|
array as the state value. For example,
|
2000-07-17 05:05:41 +02:00
|
|
|
the built-in implementation of <function>avg(float8)</function>
|
|
|
|
looks like:
|
|
|
|
|
2002-01-07 03:29:15 +01:00
|
|
|
<programlisting>
|
2006-04-15 19:45:46 +02:00
|
|
|
CREATE AGGREGATE avg (float8)
|
|
|
|
(
|
2000-07-17 05:05:41 +02:00
|
|
|
sfunc = float8_accum,
|
2000-10-23 02:46:07 +02:00
|
|
|
stype = float8[],
|
2000-07-17 05:05:41 +02:00
|
|
|
finalfunc = float8_avg,
|
2011-03-23 17:33:14 +01:00
|
|
|
initcond = '{0,0,0}'
|
1998-10-30 20:37:19 +01:00
|
|
|
);
|
2002-01-07 03:29:15 +01:00
|
|
|
</programlisting>
|
2011-03-23 21:56:55 +01:00
|
|
|
|
|
|
|
(<function>float8_accum</> requires a three-element array, not just
|
|
|
|
two elements, because it accumulates the sum of squares as well as
|
|
|
|
the sum and count of the inputs. This is so that it can be used for
|
|
|
|
some other aggregates besides <function>avg</>.)
|
2000-03-30 07:07:48 +02:00
|
|
|
</para>
|
2000-03-26 21:45:21 +02:00
|
|
|
|
2000-03-30 07:07:48 +02:00
|
|
|
<para>
|
Update documentation on may/can/might:
Standard English uses "may", "can", and "might" in different ways:
may - permission, "You may borrow my rake."
can - ability, "I can lift that log."
might - possibility, "It might rain today."
Unfortunately, in conversational English, their use is often mixed, as
in, "You may use this variable to do X", when in fact, "can" is a better
choice. Similarly, "It may crash" is better stated, "It might crash".
Also update two error messages mentioned in the documenation to match.
2007-01-31 21:56:20 +01:00
|
|
|
Aggregate functions can use polymorphic
|
2003-08-10 00:50:22 +02:00
|
|
|
state transition functions or final functions, so that the same functions
|
|
|
|
can be used to implement multiple aggregates.
|
2003-08-31 19:32:24 +02:00
|
|
|
See <xref linkend="extend-types-polymorphic">
|
2003-08-10 00:50:22 +02:00
|
|
|
for an explanation of polymorphic functions.
|
Update documentation on may/can/might:
Standard English uses "may", "can", and "might" in different ways:
may - permission, "You may borrow my rake."
can - ability, "I can lift that log."
might - possibility, "It might rain today."
Unfortunately, in conversational English, their use is often mixed, as
in, "You may use this variable to do X", when in fact, "can" is a better
choice. Similarly, "It may crash" is better stated, "It might crash".
Also update two error messages mentioned in the documenation to match.
2007-01-31 21:56:20 +01:00
|
|
|
Going a step further, the aggregate function itself can be specified
|
2006-07-27 21:52:07 +02:00
|
|
|
with polymorphic input type(s) and state type, allowing a single
|
2003-08-10 00:50:22 +02:00
|
|
|
aggregate definition to serve for multiple input data types.
|
|
|
|
Here is an example of a polymorphic aggregate:
|
|
|
|
|
|
|
|
<programlisting>
|
2006-04-15 19:45:46 +02:00
|
|
|
CREATE AGGREGATE array_accum (anyelement)
|
|
|
|
(
|
2003-08-10 00:50:22 +02:00
|
|
|
sfunc = array_append,
|
|
|
|
stype = anyarray,
|
|
|
|
initcond = '{}'
|
|
|
|
);
|
|
|
|
</programlisting>
|
|
|
|
|
|
|
|
Here, the actual state type for any aggregate call is the array type
|
2008-11-20 22:10:44 +01:00
|
|
|
having the actual input type as elements. The behavior of the aggregate
|
|
|
|
is to concatenate all the inputs into an array of that type.
|
|
|
|
(Note: the built-in aggregate <function>array_agg</> provides similar
|
|
|
|
functionality, with better performance than this definition would have.)
|
2003-08-10 00:50:22 +02:00
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
Here's the output using two different actual data types as arguments:
|
|
|
|
|
|
|
|
<programlisting>
|
|
|
|
SELECT attrelid::regclass, array_accum(attname)
|
2003-11-12 23:47:47 +01:00
|
|
|
FROM pg_attribute
|
2005-08-15 04:40:36 +02:00
|
|
|
WHERE attnum > 0 AND attrelid = 'pg_tablespace'::regclass
|
2003-11-12 23:47:47 +01:00
|
|
|
GROUP BY attrelid;
|
|
|
|
|
2005-08-15 04:40:36 +02:00
|
|
|
attrelid | array_accum
|
|
|
|
---------------+---------------------------------------
|
|
|
|
pg_tablespace | {spcname,spcowner,spclocation,spcacl}
|
2003-08-10 00:50:22 +02:00
|
|
|
(1 row)
|
|
|
|
|
2008-11-20 22:10:44 +01:00
|
|
|
SELECT attrelid::regclass, array_accum(atttypid::regtype)
|
2003-11-12 23:47:47 +01:00
|
|
|
FROM pg_attribute
|
2005-08-15 04:40:36 +02:00
|
|
|
WHERE attnum > 0 AND attrelid = 'pg_tablespace'::regclass
|
2003-11-12 23:47:47 +01:00
|
|
|
GROUP BY attrelid;
|
|
|
|
|
2008-11-20 22:10:44 +01:00
|
|
|
attrelid | array_accum
|
|
|
|
---------------+---------------------------
|
|
|
|
pg_tablespace | {name,oid,text,aclitem[]}
|
2003-08-10 00:50:22 +02:00
|
|
|
(1 row)
|
|
|
|
</programlisting>
|
|
|
|
</para>
|
|
|
|
|
2005-03-12 21:25:06 +01:00
|
|
|
<para>
|
|
|
|
A function written in C can detect that it is being called as an
|
2010-02-08 21:39:52 +01:00
|
|
|
aggregate transition or final function by calling
|
|
|
|
<function>AggCheckCallContext</>, for example:
|
2005-03-12 21:25:06 +01:00
|
|
|
<programlisting>
|
2010-07-29 21:34:41 +02:00
|
|
|
if (AggCheckCallContext(fcinfo, NULL))
|
2005-03-12 21:25:06 +01:00
|
|
|
</programlisting>
|
2009-06-20 20:45:28 +02:00
|
|
|
One reason for checking this is that when it is true for a transition
|
|
|
|
function, the first input
|
2005-03-12 21:25:06 +01:00
|
|
|
must be a temporary transition value and can therefore safely be modified
|
2011-03-23 21:56:55 +01:00
|
|
|
in-place rather than allocating a new copy.
|
|
|
|
See <literal>int8inc()</> for an example.
|
|
|
|
(This is the <emphasis>only</>
|
2009-06-20 20:45:28 +02:00
|
|
|
case where it is safe for a function to modify a pass-by-reference input.
|
|
|
|
In particular, aggregate final functions should not modify their inputs in
|
|
|
|
any case, because in some cases they will be re-executed on the same
|
|
|
|
final transition value.)
|
2005-03-12 21:25:06 +01:00
|
|
|
</para>
|
|
|
|
|
2003-08-10 00:50:22 +02:00
|
|
|
<para>
|
|
|
|
For further details see the
|
2010-04-03 09:23:02 +02:00
|
|
|
<xref linkend="sql-createaggregate">
|
2003-08-10 00:50:22 +02:00
|
|
|
command.
|
2000-03-30 07:07:48 +02:00
|
|
|
</para>
|
2003-04-10 03:22:45 +02:00
|
|
|
</sect1>
|