Zainstaluj dodatkowy moduł tablefunc raz na bazę danych, która udostępnia tę funkcję crosstab(). Od wersji Postgres 9.1 możesz CREATE EXTENSIONdo tego użyć :
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
Prosta forma - nie nadaje się do brakujących atrybutów
crosstab(text)z 1 parametrem wejściowym:
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:
Sekcja | Aktywny | Nieaktywny
--------- + -------- + ----------
A | 1 | 2)
B | 4 | 5
C | 7 | - !!
- Nie ma potrzeby przesyłania i zmiany nazw.
- Zwróć uwagę na niepoprawny wynik
C: wartość 7jest wypełniana dla pierwszej kolumny. Czasami takie zachowanie jest pożądane, ale nie w tym przypadku użycia.
- Prosta forma jest również ograniczona do dokładnie trzech kolumn w podanym zapytaniu wejściowym: nazwa_wiersza , kategoria , wartość . Nie ma miejsca na dodatkowe kolumny, jak w poniższej opcji 2-parametrowej.
Bezpieczna forma
crosstab(text, text)z 2 parametrami wejściowymi:
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:
Sekcja | Aktywny | Nieaktywny
--------- + -------- + ----------
A | 1 | 2)
B | 4 | 5
C | | 7 - !!
Zwróć uwagę na poprawny wynik dla C.
Drugim parametrem może być dowolny zapytania, który powraca jeden rząd na atrybutu dopasowanie kolejność definicji kolumnowej 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 wstępnie zdefiniowanych wariantów), zazwyczaj bardziej wydajne jest dostarczenie krótkiej listy w wyrażeniu takim jak pokazano:crosstabN()VALUES
$$VALUES ('Active'::text), ('Inactive')$$)
Lub (nie w instrukcji):
$$SELECT unnest('{Active,Inactive}'::text[])$$ -- short syntax for long lists
Użyłem wyceny w dolarach, aby ułatwić wycenę.
Możesz nawet wyprowadzać kolumny z różnymi typami danych za pomocą crosstab(text, text)- o ile reprezentacja tekstowa kolumny wartości jest poprawnym wejściem dla typu docelowego. W ten sposób można mieć atrybuty różnego rodzaju i wyjścia text, date, numericitp dla poszczególnych atrybutów. Przykład kodu znajduje się na końcu rozdziału crosstab(text, text)instrukcji .
db <> skrzypce tutaj
Zaawansowane przykłady
\crosstabview w psql
Postgres 9.6 dodał tę meta-komendę do domyślnego terminala interaktywnego psql . Możesz uruchomić zapytanie, którego użyjesz jako pierwszy crosstab()parametr, i podaj je \crosstabview(natychmiast lub w następnym kroku). Lubić:
db=> SELECT section, status, ct FROM tbl \crosstabview
Podobny wynik jak powyżej, ale jest to funkcja reprezentacji wyłącznie po stronie klienta . Wiersze wejściowe są traktowane nieco inaczej, dlatego ORDER BYnie są wymagane. Szczegóły \crosstabvieww 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):
Uprzednio zaakceptowane odpowiedź jest przestarzała.
Wariant tej funkcji crosstab(text, integer)jest przestarzały. Drugi integerparametr jest ignorowany. Cytuję obecny podręcznik :
crosstab(text sql, int N) ...
Przestarzała wersja crosstab(text). Parametr Njest teraz ignorowany, ponieważ liczba kolumn wartości jest zawsze określana przez zapytanie wywołujące
Niepotrzebne odlewanie i zmiana nazwy.
Nie powiedzie się, jeśli wiersz nie ma wszystkich atrybutów. Zobacz bezpieczny wariant z dwoma parametrami wejściowymi powyżej, aby poprawnie obsługiwać brakujące atrybuty.
ORDER BYjest wymagany w postaci jednoparametrowej crosstab(). Instrukcja:
W praktyce zapytanie SQL powinno zawsze określać, ORDER BY 1,2aby zapewnić prawidłowe uporządkowanie wierszy wejściowych