sql >> Databáze >  >> RDS >> PostgreSQL

Křížový dotaz PostgreSQL

Nainstalujte přídavný modul tablefunc jednou na databázi, která poskytuje funkci crosstab() . Od Postgres 9.1 můžete použít CREATE EXTENSION za to:

CREATE EXTENSION IF NOT EXISTS tablefunc;

Vylepšený testovací případ

CREATE TABLE tbl (
   section   text
 , status    text
 , ct        integer  -- "count" is a reserved word in standard SQL
);

INSERT INTO tbl VALUES 
  ('A', 'Active', 1), ('A', 'Inactive', 2)
, ('B', 'Active', 4), ('B', 'Inactive', 5)
                    , ('C', 'Inactive', 7);  -- ('C', 'Active') is missing

Jednoduchý formulář – nehodí se pro chybějící atributy

crosstab(text) s 1 vstupní parametr:

SELECT *
FROM   crosstab(
   'SELECT section, status, ct
    FROM   tbl
    ORDER  BY 1,2'  -- needs to be "ORDER BY 1,2" here
   ) AS ct ("Section" text, "Active" int, "Inactive" int);

Vrátí:

 Section | Active | Inactive
---------+--------+----------
 A       |      1 |        2
 B       |      4 |        5
 C       |      7 |           -- !!
  • Není potřeba casting a přejmenování.
  • Všimněte si nesprávného výsledek pro C :hodnota 7 se vyplňuje pro první sloupec. Někdy je toto chování žádoucí, ale ne pro tento případ použití.
  • Jednoduchý formulář je také omezen na přesně tři sloupce v poskytnutém vstupním dotazu:název_řádku , kategorie , hodnota . Není zde místo pro sloupce navíc jako v níže uvedené 2parametrové alternativě.

Bezpečný formulář

crosstab(text, text) s 2 vstupní parametry:

SELECT *
FROM   crosstab(
   'SELECT section, status, ct
    FROM   tbl
    ORDER  BY 1,2'  -- could also just be "ORDER BY 1" here

  , $$VALUES ('Active'::text), ('Inactive')$$
   ) AS ct ("Section" text, "Active" int, "Inactive" int);

Vrátí:

 Section | Active | Inactive
---------+--------+----------
 A       |      1 |        2
 B       |      4 |        5
 C       |        |        7  -- !!
  • Poznamenejte si správný výsledek pro C .

  • Druhý parametr může být jakýkoli dotaz, který vrací jeden řádek za atribut odpovídající pořadí definice sloupce na konci. Často budete chtít dotazovat odlišné atributy ze základní tabulky takto:

      'SELECT DISTINCT attribute FROM tbl ORDER BY 1'
    

To je v návodu.

Protože stejně musíte hláskovat všechny sloupce v seznamu definic sloupců (kromě předdefinovaných crosstabN() varianty), je obvykle efektivnější poskytnout krátký seznam v VALUES výraz jako předvedený:

    $$VALUES ('Active'::text), ('Inactive')$$)

Nebo (není v návodu):

    $$SELECT unnest('{Active,Inactive}'::text[])$$  -- short syntax for long lists
  • Použil jsem dolarové kotace aby bylo citování jednodušší.

  • Můžete dokonce vytisknout sloupce s různými datové typy s crosstab(text, text) - pokud je textová reprezentace sloupce hodnot platným vstupem pro cílový typ. Tímto způsobem můžete mít atributy různého druhu a výstup text , date , numeric atd. pro příslušné atributy. Na konci kapitoly je příklad kódu crosstab(text, text) v návodu.

db<>zde hrajte

Účinek nadbytečných vstupních řádků

S přebytečnými vstupními řádky se zachází jinak – duplicitní řádky pro stejnou kombinaci („název_řádku“, „kategorie“) – (section, status) ve výše uvedeném příkladu.

1 parametr formulář vyplní dostupné sloupce hodnot zleva doprava. Přebytečné hodnoty jsou zahozeny.
Vyhrávají dřívější vstupní řádky.

2parametr formulář přiřadí každou vstupní hodnotu jejímu vyhrazenému sloupci a přepíše jakékoli předchozí přiřazení.
Pozdější vstupní řádky vítězí.

Obvykle pro začátek nemáte duplikáty. Ale pokud tak učiníte, pečlivě upravte pořadí řazení podle svých požadavků – a zdokumentujte, co se děje.
Nebo získejte rychlé libovolné výsledky, pokud vás to nezajímá. Jen si uvědomte účinek.

Pokročilé příklady

  • Pivot on Multiple Columns pomocí Tablefunc – také demonstruje zmíněné „extra sloupce“

  • Dynamická alternativa k pivotu s CASE a GROUP BY


\crosstabview v psql

Postgres 9.6 přidal tento meta-příkaz do svého výchozího interaktivního terminálu psql. Můžete spustit dotaz, který byste použili jako první crosstab() a vložte jej do \crosstabview (ihned nebo v dalším kroku). Jako:

db=> SELECT section, status, ct FROM tbl \crosstabview

Podobný výsledek jako výše, ale jedná se o funkci reprezentace na straně klienta výhradně. Vstupní řádky jsou zpracovány mírně odlišně, proto ORDER BY není nutné. Podrobnosti pro \crosstabview v návodu. V dolní části této stránky jsou další příklady kódu.

Související odpověď na dba.SE od Daniela Véritého (autora funkce psql):

  • Jak vygeneruji pivotované CROSS JOIN, kde výsledná definice tabulky není známa?


  1. Transponujte sadu řádků jako sloupce v SQL Server 2000

  2. Jak nainstalovat SQLOPS na Mac

  3. Ztratilo se připojení k serveru MySQL při „čtení počátečního komunikačního paketu“, systémová chyba:0

  4. Můžete používat Microsoft Entity Framework s Oracle?