PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Zapytanie krzyżowe PostgreSQL

Zainstaluj dodatkowy moduł tablefunc raz na bazę danych, która udostępnia funkcję crosstab() . Od Postgres 9.1 możesz używać CREATE EXTENSION za to:

CREATE EXTENSION IF NOT EXISTS tablefunc;

Ulepszony przypadek testowy

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

Prosty formularz – nie pasuje do brakujących atrybutów

crosstab(text) z 1 parametr wejściowy:

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

Zwroty:

 Section | Active | Inactive
---------+--------+----------
 A       |      1 |        2
 B       |      4 |        5
 C       |      7 |           -- !!
  • Nie ma potrzeby przesyłania i zmiany nazwy.
  • Zwróć uwagę na niepoprawne wynik dla C :wartość 7 jest wypełniana w pierwszej kolumnie. Czasami takie zachowanie jest pożądane, ale nie w tym przypadku użycia.
  • Prosty formularz jest również ograniczony do dokładnie trzy kolumny w podanym zapytaniu wejściowym:nazwa_wiersza , kategoria , wartość . Nie ma miejsca na dodatkowe kolumny jak w 2-parametrowej alternatywie poniżej.

Bezpieczna forma

crosstab(text, text) z 2 parametry wejściowe:

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

Zwroty:

 Section | Active | Inactive
---------+--------+----------
 A       |      1 |        2
 B       |      4 |        5
 C       |        |        7  -- !!
  • Zanotuj poprawny wynik dla C .

  • drugi parametr może być dowolnym zapytaniem zwracającym jeden wiersz na atrybut pasujący do kolejności definicji kolumny na końcu. Często będziesz chciał zapytać o różne atrybuty z tabeli bazowej w następujący sposób:

      'SELECT DISTINCT attribute FROM tbl ORDER BY 1'
    

To jest w instrukcji.

Ponieważ i tak musisz przeliterować wszystkie kolumny na liście definicji kolumn (z wyjątkiem predefiniowanych crosstabN() wariantów), zazwyczaj bardziej wydajne jest dostarczenie krótkiej listy w VALUES wyrażenie jak zademonstrowano:

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

Lub (nie w instrukcji):

    $$SELECT unnest('{Active,Inactive}'::text[])$$  -- short syntax for long lists
  • Użyłem cytowania dolara aby ułatwić cytowanie.

  • Możesz nawet wyprowadzać kolumny z różnymi typy danych z crosstab(text, text) - o ile tekstowa reprezentacja kolumny wartości jest poprawnym wejściem dla typu docelowego. W ten sposób możesz mieć atrybuty różnego rodzaju i wyprowadzać text , date , numeric itp. dla odpowiednich atrybutów. Na końcu rozdziału znajduje się przykładowy kod crosstab(text, text) w instrukcji.

db<>graj tutaj

Wpływ nadmiaru wierszy wejściowych

Nadmiarowe wiersze wejściowe są obsługiwane inaczej — zduplikowane wiersze dla tej samej kombinacji („nazwa_wiersza”, „kategoria”) — (section, status) w powyższym przykładzie.

1-parametr formularz wypełnia dostępne kolumny wartości od lewej do prawej. Nadmiarowe wartości są odrzucane.
Wcześniejsze wiersze wejściowe wygrywają.

Dwuparametrowy formularz przypisuje każdą wartość wejściową do jej dedykowanej kolumny, zastępując poprzednie przypisanie.
Później wprowadzane wiersze wygrywają.

Zazwyczaj na początku nie masz duplikatów. Ale jeśli to zrobisz, ostrożnie dostosuj kolejność sortowania do swoich wymagań – i udokumentuj, co się dzieje.
Lub uzyskaj szybko dowolne wyniki, jeśli Ci to nie zależy. Po prostu bądź świadomy efektu.

Zaawansowane przykłady

  • Obróć wiele kolumn za pomocą funkcji Tablefunc – demonstruje również wspomniane „dodatkowe kolumny”

  • Dynamiczna alternatywa dla pivota z CASE i GROUP BY


\crosstabview w psql

Postgres 9,6 dodał tę meta-polecenie do domyślnego interaktywnego terminala psql. Możesz uruchomić zapytanie, którego użyjesz jako pierwszy crosstab() i prześlij go do \crosstabview (natychmiast lub w kolejnym kroku). Na przykład:

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

Wynik podobny do powyższego, ale jest to funkcja reprezentacji po stronie klienta wyłącznie. Wiersze wejściowe są traktowane nieco inaczej, dlatego ORDER BY nie jest wymagany. Szczegóły dotyczące \crosstabview w instrukcji. Na dole tej strony znajduje się więcej przykładów kodu.

Powiązana odpowiedź na dba.SE autorstwa Daniela Vérité (autora funkcji psql):

  • Jak wygenerować przestawne CROSS JOIN, gdy wynikowa definicja tabeli jest nieznana?


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Napisz szybką ramkę danych pandy do postgres

  2. Zapytanie PostgreSQL do liczenia/grupowania według dnia i wyświetlania dni bez danych

  3. Podpowiedź w PostgreSQL

  4. Generowanie identyfikatora UUID w instrukcji Postgres for Insert?

  5. brak wpisu klauzuli FROM dla tabeli Grupo cakephp