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

PostgreSQL 9.3:Tabel pivot dinamis

Anda dapat melakukannya dengan crosstab() dari tablefunc modul tambahan:

SELECT b
     , COALESCE(a1, 0) AS "A1"
     , COALESCE(a2, 0) AS "A2"
     , COALESCE(a3, 0) AS "A3"
     , ... -- all the way up to "A30"
FROM   crosstab(
         'SELECT colb, cola, 1 AS val FROM matrix
          ORDER  BY 1,2'
        , $$SELECT 'A'::text || g FROM generate_series(1,30) g$$
       ) AS t (b text
             , a1  int, a2  int, a3  int, a4  int, a5  int, a6  int
             , a7  int, a8  int, a9  int, a10 int, a11 int, a12 int
             , a13 int, a14 int, a15 int, a16 int, a17 int, a18 int
             , a19 int, a20 int, a21 int, a22 int, a23 int, a24 int
             , a25 int, a26 int, a27 int, a28 int, a29 int, a30 int);

Jika NULL bukannya 0 berfungsi juga, bisa saja SELECT * di kueri luar.
Penjelasan detail:

  • Kueri Tab Silang PostgreSQL

"Kesulitan" khusus di sini:tidak ada "nilai" yang sebenarnya. Jadi tambahkan 1 AS val sebagai kolom terakhir.

Jumlah kategori tidak diketahui

Kueri yang sepenuhnya dinamis (dengan jenis hasil yang tidak diketahui) tidak dimungkinkan dalam satu kueri. Anda membutuhkan dua pertanyaan. Pertama buat pernyataan seperti di atas secara dinamis, lalu jalankan. Detail:

  • Memilih beberapa nilai max() menggunakan satu pernyataan SQL

  • PostgreSQL mengonversi kolom menjadi baris? Transpos?

  • Buat kolom secara dinamis untuk tab silang di PostgreSQL

  • Alternatif dinamis untuk pivot dengan CASE dan GROUP BY

Terlalu banyak kategori

Jika Anda melebihi jumlah maksimum kolom (1600), tab silang klasik tidak mungkin dilakukan, karena hasilnya tidak dapat direpresentasikan dengan kolom individual. (Juga, mata manusia tidak akan bisa membaca tabel dengan kolom sebanyak itu)

Array atau jenis dokumen seperti hstore atau jsonb adalah alternatifnya. Berikut adalah solusi dengan array:

SELECT colb, array_agg(cola) AS colas
FROM  (
   SELECT colb, right(colb, -1)::int AS sortb
        , CASE WHEN m.cola IS NULL THEN 0 ELSE 1 END AS cola
   FROM        (SELECT DISTINCT colb FROM matrix) b
   CROSS  JOIN (SELECT DISTINCT cola FROM matrix) a
   LEFT   JOIN matrix m USING (colb, cola)
   ORDER  BY sortb, right(cola, -1)::int 
   ) sub
GROUP  BY 1, sortb
ORDER  BY sortb;
  • Bangun kisi nilai lengkap dengan:

                (SELECT DISTINCT colb FROM matrix) b
    CROSS  JOIN (SELECT DISTINCT cola FROM matrix) a
    
  • LEFT JOIN kombinasi yang ada, urutkan berdasarkan bagian numerik dari nama dan gabungkan ke dalam array.

    • right(colb, -1)::int memangkas karakter utama dari 'A3' dan memasukkan angka ke bilangan bulat sehingga kami mendapatkan urutan pengurutan yang tepat.

Matriks dasar

Jika Anda hanya ingin tabel 0 sebuah 1 dimana x = y , ini bisa lebih murah:

SELECT x, array_agg((x = y)::int) AS y_arr
FROM   generate_series(1,10) x
     , generate_series(1,10) y
GROUP  BY 1
ORDER  BY 1;

SQL Fiddle membangun yang Anda berikan di komentar.

Perhatikan bahwa sqlfiddle.com saat ini memiliki bug yang mematikan tampilan nilai array. Jadi saya melemparkan ke text ada untuk mengatasinya.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Dalam fungsi pemicu, cara mendapatkan bidang mana yang diperbarui

  2. Membagi Data Anda Dengan PostgreSQL 11

  3. Django:Grup Kueri Berdasarkan Bulan

  4. hibernate tidak bisa mendapatkan nilai urutan berikutnya

  5. Alat ETL Terbaik untuk Bermigrasi ke PostgreSQL