Instal modul tambahan tablefunc
satu kali per basis data, yang menyediakan fungsi crosstab()
. Sejak Postgres 9.1 Anda dapat menggunakannya CREATE EXTENSION
untuk itu:
CREATE EXTENSION IF NOT EXISTS tablefunc;
Kasing uji yang ditingkatkan
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
Bentuk sederhana - tidak cocok untuk atribut yang hilang
crosstab(text)
dengan 1 parameter input:
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);
Pengembalian:
Bagian | Aktif | Tidak aktif
--------- + -------- + ----------
A | 1 | 2
B | 4 | 5
C | 7 | - !!
- Tidak perlu casting dan penggantian nama.
- Perhatikan hasil yang salah untuk
C
: nilai 7
diisi untuk kolom pertama. Kadang-kadang, perilaku ini diinginkan, tetapi tidak untuk kasus penggunaan ini.
- Bentuk sederhana juga dibatasi tepat pada tiga kolom dalam kueri input yang disediakan: row_name , kategori , nilai . Tidak ada ruang untuk kolom tambahan seperti pada alternatif 2-parameter di bawah ini.
Bentuk yang aman
crosstab(text, text)
dengan 2 parameter input:
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);
Pengembalian:
Bagian | Aktif | Tidak aktif
--------- + -------- + ----------
A | 1 | 2
B | 4 | 5
C | | 7 - !!
Catat hasil yang benar untuk C
.
The Parameter kedua dapat permintaan apapun yang kembali satu baris per atribut yang cocok dengan urutan definisi kolom di akhir. Seringkali Anda ingin meminta atribut berbeda dari tabel yang mendasarinya seperti ini:
'SELECT DISTINCT attribute FROM tbl ORDER BY 1'
Itu ada di manual.
Karena Anda harus mengeja semua kolom dalam daftar definisi kolom (kecuali untuk varian yang telah ditentukan ), biasanya lebih efisien untuk memberikan daftar pendek dalam ekspresi seperti yang ditunjukkan:crosstabN()
VALUES
$$VALUES ('Active'::text), ('Inactive')$$)
Atau (tidak ada dalam manual):
$$SELECT unnest('{Active,Inactive}'::text[])$$ -- short syntax for long lists
Saya menggunakan kutipan dolar untuk membuat kutipan lebih mudah.
Anda bahkan dapat menampilkan kolom dengan tipe data berbeda dengan crosstab(text, text)
- selama representasi teks dari kolom nilai adalah input yang valid untuk tipe target. Dengan cara ini Anda mungkin memiliki atribut yang berbeda dan output text
, date
, numeric
dll untuk atribut masing-masing. Ada contoh kode di akhir bab crosstab(text, text)
dalam manual .
db <> biola di sini
Contoh lanjutan
\crosstabview
dalam psql
Postgres 9.6 menambahkan meta-command ini ke psql terminal interaktif default . Anda dapat menjalankan kueri yang akan Anda gunakan sebagai crosstab()
parameter pertama dan mengumpankannya \crosstabview
(segera atau pada langkah berikutnya). Suka:
db=> SELECT section, status, ct FROM tbl \crosstabview
Hasil yang sama seperti di atas, tetapi ini adalah fitur representasi di sisi klien secara eksklusif. Baris input diperlakukan sedikit berbeda, oleh karena ORDER BY
itu tidak diperlukan. Detail untuk \crosstabview
dalam manual. Ada lebih banyak contoh kode di bagian bawah halaman itu.
Jawaban terkait pada dba.SE oleh Daniel Vérité (penulis fitur psql):
The jawaban yang diterima sebelumnya sudah usang.
Varian fungsi crosstab(text, integer)
sudah usang. integer
Parameter kedua diabaikan. Saya mengutip manual saat ini :
crosstab(text sql, int N)
...
Versi usang dari crosstab(text)
. Parameter N
sekarang diabaikan, karena jumlah kolom nilai selalu ditentukan oleh kueri panggilan
Pengecoran dan penggantian nama yang tidak perlu.
Gagal jika satu baris tidak memiliki semua atribut. Lihat varian aman dengan dua parameter input di atas untuk menangani atribut yang hilang dengan benar.
ORDER BY
diperlukan dalam bentuk satu-parameter dari crosstab()
. Manual:
Dalam praktiknya, kueri SQL harus selalu menentukan ORDER BY 1,2
untuk memastikan bahwa baris input dipesan dengan benar