Home Explore Blog CI



postgresql

4th chunk of `doc/src/sgml/tablefunc.sgml`
9af47fac4f2915ae1fd666c9760e1899afadd41c536443380000000100000fa3
 produces one output row for each
    consecutive group of input rows with the same
    <structfield>row_name</structfield> value.  It fills the output
    <structfield>value</structfield> columns, left to right, with the
    <structfield>value</structfield> fields from these rows.  If there
    are fewer rows in a group than there are output <structfield>value</structfield>
    columns, the extra output columns are filled with nulls; if there are
    more rows, the extra input rows are skipped.
   </para>

   <para>
    In practice the SQL query should always specify <literal>ORDER BY 1,2</literal>
    to ensure that the input rows are properly ordered, that is, values with
    the same <structfield>row_name</structfield> are brought together and
    correctly ordered within the row.  Notice that <function>crosstab</function>
    itself does not pay any attention to the second column of the query
    result; it's just there to be ordered by, to control the order in which
    the third-column values appear across the page.
   </para>

   <para>
    Here is a complete example:
<programlisting>
CREATE TABLE ct(id SERIAL, rowid TEXT, attribute TEXT, value TEXT);
INSERT INTO ct(rowid, attribute, value) VALUES('test1','att1','val1');
INSERT INTO ct(rowid, attribute, value) VALUES('test1','att2','val2');
INSERT INTO ct(rowid, attribute, value) VALUES('test1','att3','val3');
INSERT INTO ct(rowid, attribute, value) VALUES('test1','att4','val4');
INSERT INTO ct(rowid, attribute, value) VALUES('test2','att1','val5');
INSERT INTO ct(rowid, attribute, value) VALUES('test2','att2','val6');
INSERT INTO ct(rowid, attribute, value) VALUES('test2','att3','val7');
INSERT INTO ct(rowid, attribute, value) VALUES('test2','att4','val8');

SELECT *
FROM crosstab(
  'select rowid, attribute, value
   from ct
   where attribute = ''att2'' or attribute = ''att3''
   order by 1,2')
AS ct(row_name text, category_1 text, category_2 text, category_3 text);

 row_name | category_1 | category_2 | category_3
----------+------------+------------+------------
 test1    | val2       | val3       |
 test2    | val6       | val7       |
(2 rows)
</programlisting>
   </para>

   <para>
    You can avoid always having to write out a <literal>FROM</literal> clause to
    define the output columns, by setting up a custom crosstab function that
    has the desired output row type wired into its definition.  This is
    described in the next section.  Another possibility is to embed the
    required <literal>FROM</literal> clause in a view definition.
   </para>

   <note>
    <para>
     See also the <command><link linkend="app-psql-meta-commands-crosstabview">\crosstabview</link></command>
     command in <application>psql</application>, which provides functionality similar
     to <function>crosstab()</function>.
    </para>
   </note>

  </sect3>

  <sect3 id="tablefunc-functions-crosstab-n-text">
   <title><function>crosstab<replaceable>N</replaceable>(text)</function></title>

   <indexterm>
    <primary>crosstab</primary>
   </indexterm>

<synopsis>
crosstab<replaceable>N</replaceable>(text sql)
</synopsis>

    <para>
     The <function>crosstab<replaceable>N</replaceable></function> functions are examples of how
     to set up custom wrappers for the general <function>crosstab</function> function,
     so that you need not write out column names and types in the calling
     <command>SELECT</command> query.  The <filename>tablefunc</filename> module includes
     <function>crosstab2</function>, <function>crosstab3</function>, and
     <function>crosstab4</function>, whose output row types are defined as
    </para>

<programlisting>
CREATE TYPE tablefunc_crosstab_N AS (
    row_name TEXT,
    category_1 TEXT,
    category_2 TEXT,
        .
        .
        .
    category_N TEXT
);
</programlisting>

    <para>
     Thus, these functions can be used directly when the input query produces
     <structfield>row_name</structfield> and <structfield>value</structfield>

Title: crosstab Function Details, Examples, and Custom Wrappers
Summary
This section delves into the specifics of how the crosstab function handles input rows and fills output columns, emphasizing the importance of the ORDER BY clause in the input SQL query. It provides a complete example demonstrating how to use the function, and suggests ways to simplify its usage by creating custom crosstab functions with predefined output row types. It also mentions the crosstabview command in psql as an alternative, and introduces crosstabN functions (crosstab2, crosstab3, crosstab4) as examples of custom wrappers that eliminate the need to specify output column names and types in the SELECT query, using predefined types like tablefunc_crosstab_N.