sql >> Database >  >> RDS >> PostgreSQL

Kruistabel om zoekvraag te transponeren

De speciale moeilijkheid is dat uw gegevens niet klaar zijn voor kruistabellen. U hebt gegevens nodig in de vorm row_name , categorie , waarde . Je kunt dat krijgen met een UNION vraag:

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;

Maar een slimme LATERAL query heeft slechts een enkele tabelscan nodig en zal sneller zijn:

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;

Gerelateerd:

Gebruik de eenvoudige vorm van crosstab() met 1 parameter met deze vraag als invoer:

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

Lijst landnamen in alfabetisch aflopende volgorde (zoals in uw demo). Dit veronderstelt ook dat alle statistieken zijn gedefinieerd NOT NULL .

Als een of beide niet het geval is, gebruikt u in plaats daarvan het 2-parameterformulier:

Toevoegen "rollup"

D.w.z. totalen per statistiek:

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' is een willekeurig label, dat als laatste alfabetisch moet worden gesorteerd (of je hebt de 2-parametervorm van crosstab() nodig ).

Als u veel heeft van metrische kolommen, wilt u misschien de querytekenreeks dynamisch opbouwen. Gerelateerd:

Merk ook op dat de aanstaande Postgres 9.5 (momenteel bèta) een speciale SQL-clausule voor ROLLUP .
Gerelateerd:




  1. Doorgaan met while-lus na uitzondering in SQL?

  2. Hoe MySQL Workbench op Windows te installeren

  3. Hoe een lijst met datums tussen twee datums in mysql select query te krijgen

  4. Hoe Cotd() werkt in PostgreSQL