Zainstaluj dodatkowy moduł tablefunc
raz na bazę danych, która udostępnia tę funkcję crosstab()
. Od wersji Postgres 9.1 możesz CREATE EXTENSION
do 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ść 7
jest 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
, numeric
itp 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 BY
nie są wymagane. Szczegóły \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):
Uprzednio zaakceptowane odpowiedź jest przestarzała.
Wariant tej funkcji crosstab(text, integer)
jest przestarzały. Drugi integer
parametr jest ignorowany. Cytuję obecny podręcznik :
crosstab(text sql, int N)
...
Przestarzała wersja crosstab(text)
. Parametr N
jest 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 BY
jest wymagany w postaci jednoparametrowej crosstab()
. Instrukcja:
W praktyce zapytanie SQL powinno zawsze określać, ORDER BY 1,2
aby zapewnić prawidłowe uporządkowanie wierszy wejściowych