Home Explore Blog CI



postgresql

7th chunk of `doc/src/sgml/tablefunc.sgml`
ff03fb5608b26c100fb43fe8373798e10ece21f74a9f5a360000000100000fad

<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>
                  &lt;==  value  columns   ==&gt;
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 output
    columns of the proper data types.  If there are <replaceable>N</replaceable>
    columns in the <parameter>source_sql</parameter> query's result, the first
    <replaceable>N</replaceable>-2 of them must match up with the first
    <replaceable>N</replaceable>-2 output columns.  The remaining output columns
    must have the type of the last column of the <parameter>source_sql</parameter>
    query's result, and there must be exactly as many of them as there
    are rows in the <parameter>category_sql</parameter> query's result.
   </para>

   <para>
    The <function>crosstab</function> function produces one output row for each
    consecutive group of input rows with the same
    <structfield>row_name</structfield> value.  The output
    <structfield>row_name</structfield> column, plus any <quote>extra</quote>
    columns, are copied from the first row of the group.  The output
    <structfield>value</structfield> columns are filled with the
    <structfield>value</structfield> fields from rows having matching
    <structfield>category</structfield> values.  If a row's <structfield>category</structfield>
    does not match any output of the <parameter>category_sql</parameter>
    query, its <structfield>value</structfield> is ignored.  Output
    columns whose matching category is not present in any input row
    of the group are filled with nulls.
   </para>

   <para>
    In practice the <parameter>source_sql</parameter> query should always
    specify <literal>ORDER BY 1</literal> to ensure that values with the same
    <structfield>row_name</structfield> are brought together.  However,
    ordering of the categories within a group is not important.
    Also, it is essential to be sure that the order of the
    <parameter>category_sql</parameter> query's output matches the specified
    output column order.
   </para>

   <para>
    Here are two complete examples:
<programlisting>
create table sales(year int, month int, qty int);
insert into sales values(2007, 1, 1000);
insert into sales values(2007, 2, 1500);
insert into sales values(2007, 7, 500);
insert into sales values(2007, 11, 1500);
insert into sales values(2007, 12, 2000);
insert into sales values(2008, 1, 1000);

select * from crosstab(
  'select year, month, qty from sales order by 1',
  'select m from generate_series(1,12) m'
) as (
  year int,
  "Jan" int,
  "Feb" int,
  "Mar" int,
  "Apr" int,
  "May" int,
  "Jun" int,
  "Jul" int,
  "Aug" int,
  "Sep" int,
  "Oct" int,
  "Nov" int,
  "Dec" int
);
 year | Jan  | Feb  | Mar | Apr | May | Jun | Jul | Aug | Sep | Oct | Nov  | Dec
------+------+------+-----+-----+-----+-----+-----+-----+-----+-----+------+------
 2007 | 1000 | 1500 |     |     |     |     | 500 |     |     |     | 1500 | 2000
 2008 | 1000 |      |     |     |     |     |     |     |     |     |      |
(2 rows)
</programlisting>

<programlisting>
CREATE TABLE cth(rowid text, rowdt timestamp, attribute text, val text);
INSERT INTO cth VALUES('test1','01

Title: Detailed Explanation and Examples of the Two-Parameter crosstab Function
Summary
This section elaborates on the two-parameter crosstab function, explaining how to define output columns and their data types using the FROM clause in the calling SELECT statement. It specifies the relationship between the columns in the source_sql query and the output columns, emphasizing the importance of matching the data types and ensuring the correct number of output columns based on the category_sql query. It explains how the function handles grouping of input rows based on row_name, copying data from the first row of each group and filling value columns based on matching categories, using nulls where necessary. The section also stresses the importance of ordering in the source_sql and category_sql queries. Finally, it provides two complete examples using sales data and a cth table to demonstrate the practical application of the crosstab function.