Generar columnas dinámicamente en PostgreSQL

He visto que hay algunas preguntas similares como esta, pero no he entendido cómo codificarlo yo mismo. Tenga en cuenta que solo soy un principiante en este campo.

Básicamente quiero pivotar la tabla así:

zoom |    day     | point         zoom | 2015-10-01 |  2015-10-02 | ......
------+-----------+-------  ---> ------+------------+-------------+
   1 | 2015-10-01 |   201            1 |    201     |     685     |
   2 | 2015-10-01 |    43            2 |     43     |     346     | 
   3 | 2015-10-01 |    80            3 |     80     |     534     | 
   4 | 2015-10-01 |   324            4 |    324     |     786     | 
   5 | 2015-10-01 |    25            5 |     25     |     685     |
   1 | 2015-10-02 |   685 
   2 | 2015-10-02 |   346 
   3 | 2015-10-02 |   534 
   4 | 2015-10-02 |   555 
   5 | 2015-10-02 |   786
   :
   :
   :

El tiempo puede variar

Resultados a la izquierda que obtengo con:

SELECT 
zoom,
to_char(date_trunc('day', time), 'YYYY-MM-DD') AS day,
count(*) as point
FROM province
WHERE time >= '2015-05-01' AND time < '2015-06-01'
GROUP BY to_char(date_trunc('day', time), 'YYYY-MM-DD'), zoom;

He leído que hay algunos problemas si usocount y también que sería mejor si usoCASE yGROUP BY, sin embargo, no tengo idea de cómoCASE esta.

Crosstab en sí mismo no admite la creación dinámica de nombres de columnas, pero eso se puede lograr concrosstab_hash, si lo entendí correctamente.

Probablemente esta sea una buena solución:http://okbob.blogspot.ca/2008/08/using-cursors-for-generating-cross.html Sin embargo, estoy atascado con él tratando de programarlo yo mismo.

Tengo que usar este tipo de pivote con bastante frecuencia, por lo que solicitaría cualquier tipo de ayuda y explicación adicional detrás de esto.

Editar1

Estoy tratando de descubrir cómo funciona la tabla de referencias cruzadas con las fechas, actualmente sin devolver nombres dinámicos de columnas. Más adelante explicaré por qué. Está relacionado con la pregunta principal. Para este ejemplo, estoy usando solo un período de 2 fechas.

Basado en la respuesta de @Erwin Brandstetter:

SELECT * FROM crosstab(
       'SELECT zoom, day, point
        FROM   province
        ORDER  BY 1, 2'
      , $VALUES ('2015-10-01'::date), ('2015-10-02')$)
AS ct (zoom text, day1 int, day2 int);

Los resultados devueltos son:

zoom |    day1    |    day2     | 
-----+------------+-------------+
   1 |    201     |     685     |
   2 |     43     |     346     | 
   3 |     80     |     534     | 
   4 |    324     |     786     | 

Estoy tratando de conseguir esto

zoom | 2015-10-01 |  2015-10-02 | 
-----+------------+-------------+
   1 |    201     |     685     |
   2 |     43     |     346     | 
   3 |     80     |     534     | 
   4 |    324     |     786     | 

pero mi consulta no funciona:

SELECT *
FROM crosstab(
      'SELECT *
       FROM province
       ORDER  BY 1,2')
AS ct (zoom text, "2015-10-01" date, "2015-10-02" date);

ERROR:  return and sql tuple descriptions are incompatible

Edit1, Q1. ¿Por qué esto no funciona y cómo puedo devolver resultados como ese?

He leído los enlaces que @Erwin Brandstetter me proporcionó, especialmente este:Ejecutar una consulta de tabla cruzada dinámica. He copiado / pegado su función:

CREATE OR REPLACE FUNCTION pivottab(_tbl regclass, 
                                    _row text, _cat text, 
                                    _expr text,
                                    _type regtype)  
RETURNS text AS
$func$
DECLARE
   _cat_list text;
   _col_list text;
BEGIN
-- generate categories for xtab param and col definition list    
EXECUTE format(
 $SELECT string_agg(quote_literal(x.cat), '), (')
        , string_agg(quote_ident  (x.cat), %L)
   FROM  (SELECT DISTINCT %I AS cat FROM %s ORDER BY 1) x$
 , ' ' || _type || ', ', _cat, _tbl)
INTO  _cat_list, _col_list;

-- generate query string
RETURN format(
'SELECT * FROM crosstab(
   $q$SELECT %I, %I, %s
      FROM   %I
      GROUP  BY 1, 2
      ORDER  BY 1, 2$q$
 , $c$VALUES (%5$s)$c$
   ) ct(%1$I text, %6$s %7$s)'
, _row, _cat, _expr, _tbl, _cat_list, _col_list, _type
);

END
$func$ LANGUAGE plpgsql;

y llamarlo con consulta

SELECT pivottab('province','zoom','day','point','date');

La función me devolvió:

                         pivottab                         
----------------------------------------------------------
 SELECT * FROM crosstab(                                 +
    $q$SELECT zoom, day, point                           +
       FROM   province                                   +
       GROUP  BY 1, 2                                    +
       ORDER  BY 1, 2$q$                                 +
  , $c$VALUES ('2015-10-01'), ('2015-10-02')$c$          +
    ) ct(zoom text, "2015-10-01" date, "2015-10-02" date)
(1 row)

Entonces, cuando edité la consulta y agregué; (sería bueno que ya esté allí) obtuve:

ERROR:  column "province.point" must appear in the GROUP BY clause or be used in an aggregate function

Edit1, Q2. ¿Alguna idea de cómo solos esto?

Edit1, Q3. Supongo que la siguiente pregunta será cómo ejecutar la función automáticamente, que también se menciona en el mismo enlace, pero quedó bloqueado en los pasos anteriores.

Respuestas a la pregunta(1)

Su respuesta a la pregunta