FUNCTION crosstab_float8_5_cols(
IN text,
OUT my_row_name text,
OUT my_category_1 float8,
OUT my_category_2 float8,
OUT my_category_3 float8,
OUT my_category_4 float8,
OUT my_category_5 float8)
RETURNS setof record
AS '$libdir/tablefunc','crosstab' LANGUAGE C STABLE STRICT;
</programlisting>
</para>
</listitem>
</itemizedlist>
</para>
</sect3>
<sect3 id="tablefunc-functions-crosstab-text-2">
<title><function>crosstab(text, text)</function></title>
<indexterm>
<primary>crosstab</primary>
</indexterm>
<synopsis>
crosstab(text source_sql, text category_sql)
</synopsis>
<para>
The main limitation of the single-parameter form of <function>crosstab</function>
is that it treats all values in a group alike, inserting each value into
the first available column. If you want the value
columns to correspond to specific categories of data, and some groups
might not have data for some of the categories, that doesn't work well.
The two-parameter form of <function>crosstab</function> handles this case by
providing an explicit list of the categories corresponding to the
output columns.
</para>
<para>
<parameter>source_sql</parameter> is an SQL statement that produces the
source set of data. This statement must return one
<structfield>row_name</structfield> column, one
<structfield>category</structfield> column, and one
<structfield>value</structfield> column. It may also have one or more
<quote>extra</quote> columns.
The <structfield>row_name</structfield> column must be first. The
<structfield>category</structfield> and <structfield>value</structfield>
columns must be the last two columns, in that order. Any columns between
<structfield>row_name</structfield> and
<structfield>category</structfield> are treated as <quote>extra</quote>.
The <quote>extra</quote> columns are expected to be the same for all rows
with the same <structfield>row_name</structfield> value.
</para>
<para>
For example, <parameter>source_sql</parameter> might produce a set
something like:
<programlisting>
SELECT row_name, extra_col, cat, value FROM foo ORDER BY 1;
row_name extra_col cat value
----------+------------+-----+---------
row1 extra1 cat1 val1
row1 extra1 cat2 val2
row1 extra1 cat4 val4
row2 extra2 cat1 val5
row2 extra2 cat2 val6
row2 extra2 cat3 val7
row2 extra2 cat4 val8
</programlisting>
</para>
<para>
<parameter>category_sql</parameter> is an SQL statement that produces
the set of categories. This statement must return only one column.
It must produce at least one row, or an error will be generated.
Also, it must not produce duplicate values, or an error will be
generated. <parameter>category_sql</parameter> might be something like:
<programlisting>
SELECT DISTINCT cat FROM foo ORDER BY 1;
cat
-------
cat1
cat2
cat3
cat4
</programlisting>
</para>
<para>
The <function>crosstab</function> function is declared to return <type>setof
record</type>, so the actual names and types of the output columns must be
defined in the <literal>FROM</literal> clause of the calling <command>SELECT</command>
statement, for example:
<programlisting>
SELECT * FROM crosstab('...', '...')
AS ct(row_name text, extra text, cat1 text, cat2 text, cat3 text, cat4 text);
</programlisting>
</para>
<para>
This will produce a result something like:
<programlisting>
<== value columns ==>
row_name extra cat1 cat2 cat3 cat4
---------+-------+------+------+------+------
row1 extra1 val1 val2 val4
row2 extra2 val5 val6 val7 val8
</programlisting>
</para>
<para>
The <literal>FROM</literal> clause must define the proper number of