sql >> Base de Datos >  >> RDS >> PostgreSQL

Pivote en múltiples columnas usando Tablefunc

El problema con tu consulta es que b y c compartir la misma marca de tiempo 2012-01-02 00:00:00 , y tienes la timestamp columna timeof primero en su consulta, por lo que, aunque haya agregado énfasis en negrita, b y c son solo columnas adicionales que caen en el mismo grupo 2012-01-02 00:00:00 . Solo el primero (b ) se devuelve desde (citando el manual):

El row_name la columna debe ser la primera. La category y value las columnas deben ser las dos últimas columnas, en ese orden. Cualquier columna entre row_name y category se tratan como "extra". Se espera que las columnas "extra" sean las mismas para todas las filas con el mismo row_name valor.

El énfasis en negrita es mío.
Simplemente invierta el orden de las dos primeras columnas para hacer entity el nombre de la fila y funciona como se desea:

SELECT * FROM crosstab(
      'SELECT entity, timeof, status, ct
       FROM   t4
       ORDER  BY 1'
      ,'VALUES (1), (0)')
 AS ct (
    "Attribute" character
   ,"Section" timestamp
   ,"status_1" int
   ,"status_0" int);

entity debe ser único, por supuesto.

Reiterar

  • row_name primero
  • (opcional) extra columnas siguiente
  • category (según lo definido por el segundo parámetro) y value último .

Las columnas adicionales se rellenan desde el primero fila de cada row_name dividir. Los valores de otras filas se ignoran, solo hay una columna por row_name llenar. Por lo general, serían los mismos para cada fila de un row_name , pero eso depende de ti.

Para la configuración diferente en su respuesta:

SELECT localt, entity
     , msrmnt01, msrmnt02, msrmnt03, msrmnt04, msrmnt05  -- , more?
FROM   crosstab(
        'SELECT dense_rank() OVER (ORDER BY localt, entity)::int AS row_name
              , localt, entity -- additional columns
              , msrmnt, val
         FROM   test
         -- WHERE  ???   -- instead of LIMIT at the end
         ORDER  BY localt, entity, msrmnt
         -- LIMIT ???'   -- instead of LIMIT at the end
     , $$SELECT generate_series(1,5)$$)  -- more?
     AS ct (row_name int, localt timestamp, entity int
          , msrmnt01 float8, msrmnt02 float8, msrmnt03 float8, msrmnt04 float8, msrmnt05 float8 -- , more?
            )
LIMIT 1000  -- ??!!

No es de extrañar que las consultas en su prueba funcionen terriblemente. Su configuración de prueba tiene 14 millones de filas y usted procesa todas de ellos antes de tirar la mayor parte con LIMIT 1000 . Para obtener un conjunto de resultados reducido, agregue condiciones DONDE o un LÍMITE a la consulta de origen.

Además, la matriz con la que trabaja es innecesariamente costosa. Genero un nombre de fila sustituto con dense_rank() en su lugar.

db<>violín aquí, con una configuración de prueba más simple y menos filas.