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

Solicitud de consulta de transposición de tabulación cruzada

La dificultad especial es que sus datos no están listos para la tabulación cruzada. Necesita datos en la forma row_name , categoría , valor . Puedes obtener eso con un UNION consulta:

SELECT 'metric1' AS metric, country_code, metric1 FROM tbl1
UNION ALL
SELECT 'metric2' AS metric, country_code, metric2 FROM tbl1
UNION ALL
SELECT 'metric3' AS metric, country_code, metric3 FROM tbl1
ORDER  BY 1, 2 DESC;

Pero un LATERAL inteligente la consulta solo necesita un escaneo de tabla y será más rápida:

SELECT x.metric, t.country_code, x.val
FROM   tbl1 t
     , LATERAL (VALUES
         ('metric1', metric1)
       , ('metric2', metric2)
       , ('metric3', metric3)
       ) x(metric, val)
ORDER  BY 1, 2 DESC;

Relacionado:

Usando la forma simple de crosstab() con 1 parámetro con esta consulta como entrada:

SELECT * FROM crosstab(
 $$SELECT x.metric, t.country_code, x.val
   FROM   tbl1 t
        , LATERAL (VALUES
            ('metric1', metric1)
          , ('metric2', metric2)
          , ('metric3', metric3)
          ) x(metric, val)
   ORDER  BY 1, 2 DESC$$
   )
AS ct (metric text, us int, uk int, fr int);

Enumere los nombres de los países en orden alfabético descendente (como en su demostración). Esto también supone que todas las métricas están definidas NOT NULL .

Si uno o ambos no son el caso, utilice la forma de 2 parámetros en su lugar:

Añadir "resumen"

Es decir. totales por métrica:

SELECT * FROM crosstab(
 $$SELECT x.metric, t.country_code, x.val
   FROM  (
      TABLE tbl1
      UNION ALL
      SELECT 'zzz_total', sum(metric1)::int, sum(metric2)::int, sum(metric3)::int  -- etc.
      FROM tbl1
      ) t
        , LATERAL (VALUES
            ('metric1', metric1)
          , ('metric2', metric2)
          , ('metric3', metric3)
          ) x(metric, val)
   ORDER  BY 1, 2 DESC$$
   )
AS ct (metric text, total int, us int, uk int, fr int);

'zzz_total' es una etiqueta arbitraria, que debe ordenarse en último lugar alfabéticamente (o necesita la forma de 2 parámetros de crosstab() ).

Si tienes muchos de columnas de métricas, es posible que desee generar la cadena de consulta dinámicamente. Relacionado:

También tenga en cuenta que el próximo Postgres 9.5 (actualmente beta) presenta un Cláusula SQL para ROLLUP .
Relacionado: