sql >> Databasteknik >  >> RDS >> PostgreSQL

Korstabelltransponeringsförfrågan

Den speciella svårigheten är att dina data inte är redo för korstabulering. Du behöver data i formen radnamn , kategori , värde . Du kan få det med en UNION fråga:

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;

Men en smart LATERAL fråga behöver bara en enda tabellskanning och kommer att vara snabbare:

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;

Relaterat:

Med den enkla formen crosstab() med 1 parameter med denna fråga som indata:

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);

Lista landsnamn i alfabetiskt fallande ordning (som i din demo). Detta förutsätter också att alla mätvärden är definierade NOT NULL .

Om en eller båda inte är fallet, använd istället formuläret med två parametrar:

Lägg till "samlad"

d.v.s. totalt per mätvärde:

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' är en godtycklig etikett som måste sorteras sist i alfabetisk ordning (eller så behöver du 2-parametersformen crosstab() ).

Om du har massor av statistikkolumner, kanske du vill bygga frågesträngen dynamiskt. Relaterat:

Observera också att den kommande Postgres 9.5 (för närvarande beta) introducerar en dedikerad SQL-sats för ROLLUP .
Relaterat:




  1. Ändra alla tabeller i databasen

  2. MySQL - uppdaterar alla poster för att matcha maxvärdet i gruppen

  3. MySQL:Vad är en sida?

  4. Uppdatera n slumpmässiga rader i SQL