Home Explore Blog CI



postgresql

4th chunk of `doc/src/sgml/xaggr.sgml`
d46a6a114dea065ab206ca038732f4a8c8b8e4a3fb3003c70000000100000fac
 frame starting position.  This convention allows moving-aggregate
   mode to be used in situations where there are some infrequent cases that
   are impractical to reverse out of the running state value.  The inverse
   transition function can <quote>punt</quote> on these cases, and yet still come
   out ahead so long as it can work for most cases.  As an example, an
   aggregate working with floating-point numbers might choose to punt when
   a <literal>NaN</literal> (not a number) input has to be removed from the running
   state value.
  </para>

  <para>
   When writing moving-aggregate support functions, it is important to be
   sure that the inverse transition function can reconstruct the correct
   state value exactly.  Otherwise there might be user-visible differences
   in results depending on whether the moving-aggregate mode is used.
   An example of an aggregate for which adding an inverse transition
   function seems easy at first, yet where this requirement cannot be met
   is <function>sum</function> over <type>float4</type> or <type>float8</type> inputs.  A
   naive declaration of <function>sum(<type>float8</type>)</function> could be

<programlisting>
CREATE AGGREGATE unsafe_sum (float8)
(
    stype = float8,
    sfunc = float8pl,
    mstype = float8,
    msfunc = float8pl,
    minvfunc = float8mi
);
</programlisting>

   This aggregate, however, can give wildly different results than it would
   have without the inverse transition function. For example, consider

<programlisting>
SELECT
  unsafe_sum(x) OVER (ORDER BY n ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING)
FROM (VALUES (1, 1.0e20::float8),
             (2, 1.0::float8)) AS v (n,x);
</programlisting>

   This query returns <literal>0</literal> as its second result, rather than the
   expected answer of <literal>1</literal>.  The cause is the limited precision of
   floating-point values: adding <literal>1</literal> to <literal>1e20</literal> results
   in <literal>1e20</literal> again, and so subtracting <literal>1e20</literal> from that
   yields <literal>0</literal>, not <literal>1</literal>.  Note that this is a limitation
   of floating-point arithmetic in general, not a limitation
   of <productname>PostgreSQL</productname>.
  </para>

 </sect2>

 <sect2 id="xaggr-polymorphic-aggregates">
  <title>Polymorphic and Variadic Aggregates</title>

  <indexterm>
   <primary>aggregate function</primary>
   <secondary>polymorphic</secondary>
  </indexterm>

  <indexterm>
   <primary>aggregate function</primary>
   <secondary>variadic</secondary>
  </indexterm>

  <para>
   Aggregate functions can use polymorphic
   state transition functions or final functions, so that the same functions
   can be used to implement multiple aggregates.
   See <xref linkend="extend-types-polymorphic"/>
   for an explanation of polymorphic functions.
   Going a step further, the aggregate function itself can be specified
   with polymorphic input type(s) and state type, allowing a single
   aggregate definition to serve for multiple input data types.
   Here is an example of a polymorphic aggregate:

<programlisting>
CREATE AGGREGATE array_accum (anycompatible)
(
    sfunc = array_append,
    stype = anycompatiblearray,
    initcond = '{}'
);
</programlisting>

   Here, the actual state type for any given aggregate call is the array type
   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</function> provides similar
   functionality, with better performance than this definition would have.)
  </para>

  <para>
   Here's the output using two different actual data types as arguments:

<programlisting>
SELECT attrelid::regclass, array_accum(attname)
    FROM pg_attribute
    WHERE attnum &gt; 0 AND attrelid = 'pg_tablespace'::regclass
    GROUP BY attrelid;

   attrelid    |              array_accum
---------------+---------------------------------------

Title: Aggregate Functions with Inverse Transition and Polymorphism
Summary
The inverse transition function in moving-aggregate mode can 'punt' on difficult cases, and aggregate functions can be written with polymorphic state transition functions or final functions to implement multiple aggregates, with examples including sum over float4 or float8 inputs and a polymorphic aggregate array_accum for concatenating inputs into an array.