PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Kueri Tab Silang PostgreSQL

Instal modul tambahan tablefunc sekali per database, yang menyediakan fungsi crosstab() . Sejak Postgres 9.1 Anda dapat menggunakan CREATE EXTENSION untuk itu:

CREATE EXTENSION IF NOT EXISTS tablefunc;

Kasus 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 masukan:

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:

 Section | Active | Inactive
---------+--------+----------
 A       |      1 |        2
 B       |      4 |        5
 C       |      7 |           -- !!
  • Tidak perlu casting dan mengganti nama.
  • Perhatikan yang salah hasil untuk C :nilai 7 diisi untuk kolom pertama. Terkadang, perilaku ini diinginkan, tetapi tidak untuk kasus penggunaan ini.
  • Bentuk sederhana juga terbatas pada tepat 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.

Formulir aman

crosstab(text, text) dengan 2 parameter masukan:

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:

 Section | Active | Inactive
---------+--------+----------
 A       |      1 |        2
 B       |      4 |        5
 C       |        |        7  -- !!
  • Perhatikan hasil yang benar untuk C .

  • parameter kedua dapat berupa kueri apa pun yang mengembalikan satu baris per atribut yang cocok dengan urutan definisi kolom di bagian akhir. Seringkali Anda ingin menanyakan atribut yang berbeda dari tabel yang mendasarinya seperti ini:

      'SELECT DISTINCT attribute FROM tbl ORDER BY 1'
    

Itu ada di manual.

Karena Anda tetap harus mengeja semua kolom dalam daftar definisi kolom (kecuali untuk crosstabN() varian), biasanya lebih efisien untuk memberikan daftar pendek dalam VALUES ekspresi seperti yang ditunjukkan:

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

Atau (tidak ada di 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 berbeda tipe data dengan crosstab(text, text) - selama representasi teks dari kolom nilai adalah input yang valid untuk jenis target. Dengan cara ini Anda mungkin memiliki atribut yang berbeda jenis dan menghasilkan text , date , numeric dll untuk atribut masing-masing. Ada contoh kode di akhir bab crosstab(text, text) dalam manual.

db<>main biola di sini

Efek dari baris masukan yang berlebihan

Baris input berlebih ditangani secara berbeda - baris duplikat untuk kombinasi ("row_name", "category") yang sama - (section, status) dalam contoh di atas.

1-parameter form mengisi kolom nilai yang tersedia dari kiri ke kanan. Nilai berlebih dibuang.
Baris masukan sebelumnya menang.

2-parameter form menetapkan setiap nilai masukan ke kolom khusus, menimpa tugas sebelumnya.
Baris masukan selanjutnya menang.

Biasanya, Anda tidak memiliki duplikat untuk memulai. Tetapi jika Anda melakukannya, sesuaikan urutan pengurutan dengan kebutuhan Anda dengan hati-hati - dan dokumentasikan apa yang terjadi.
Atau dapatkan hasil arbitrer cepat jika Anda tidak peduli. Waspadai efeknya.

Contoh lanjutan

  • Pivot pada Beberapa Kolom menggunakan Tablefunc - juga menunjukkan "kolom tambahan" yang disebutkan

  • Alternatif dinamis untuk pivot dengan CASE dan GROUP BY


\crosstabview di psql

Postgres 9.6 menambahkan perintah-meta ini ke terminal interaktif default psql. Anda dapat menjalankan kueri yang akan Anda gunakan sebagai crosstab() pertama parameter dan masukkan ke \crosstabview (segera atau di langkah berikutnya). Seperti:

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

Hasil serupa seperti di atas, tetapi merupakan fitur representasi di sisi klien khusus. Baris input diperlakukan sedikit berbeda, oleh karena itu ORDER BY tidak diperlukan. Detail untuk \crosstabview dalam manual. Ada lebih banyak contoh kode di bagian bawah halaman itu.

Jawaban terkait di dba.SE oleh Daniel Vérité (penulis fitur psql):

  • Bagaimana cara menghasilkan CROSS JOIN berporos di mana definisi tabel yang dihasilkan tidak diketahui?


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Rel Migrasi mengubah kolom untuk menggunakan array Postgres

  2. postgres kueri dinamis

  3. Bekerja menuju Postgres-XL 9.5

  4. Bagaimana date_trunc() Bekerja di PostgreSQL

  5. pemilik database postgresql tidak dapat mengakses database - Tidak ada hubungan yang ditemukan.