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

Memilih beberapa nilai max() menggunakan satu pernyataan SQL

Sekali lagi, untuk lebih dari beberapa "tipe data", saya sarankan untuk menggunakan crosstab() :

SELECT * FROM crosstab(
     $$SELECT DISTINCT ON (1, 2)
              'max' AS "type", data_type, val
       FROM   tbl
       ORDER  BY 1, 2, val DESC$$

    ,$$VALUES ('Final Fantasy'), ('Quake 3'), ('World of Warcraft')$$)
AS x ("type" text, "Final Fantasy" int, "Quake 3" int, "World of Warcraft" int)

Pengembalian:

type | Final Fantasy | Quake 3 | World of Warcraft
-----+---------------+---------+-------------------
max  | 500           | 1500    |    1200

Penjelasan lebih lanjut untuk dasar-dasarnya:
Kueri Crosstab PostgreSQL

Solusi dinamis

Hal yang sulit adalah membuat sepenuhnya dinamis :untuk membuatnya bekerja untuk

  • nomor tidak dikenal kolom (tipe_data dalam hal ini)
  • dengan nama tidak dikenal (tipe_data lagi)

Setidaknya jenis terkenal:integer dalam hal ini.

Singkatnya:itu tidak mungkin dengan PostgreSQL saat ini (termasuk 9.3). Ada perkiraan dengan tipe polimorfik dan cara untuk menghindari pembatasan dengan array atau tipe hstore. Mungkin cukup baik untuk Anda. Tapi itu sangat tidak mungkin untuk mendapatkan hasil dengan kolom individual dalam satu kueri SQL. SQL sangat kaku tentang tipe dan ingin tahu apa yang diharapkan kembali.

Namun , itu bisa dilakukan dengan dua pertanyaan. Yang pertama membangun kueri aktual untuk digunakan. Berdasarkan kasus sederhana di atas:

SELECT $f$SELECT * FROM crosstab(
     $$SELECT DISTINCT ON (1, 2)
              'max' AS "type", data_type, val
       FROM   tbl
       ORDER  BY 1, 2, val DESC$$

    ,$$VALUES ($f$     || string_agg(quote_literal(data_type), '), (') || $f$)$$)
AS x ("type" text, $f$ || string_agg(quote_ident(data_type), ' int, ') || ' int)'
FROM  (SELECT DISTINCT data_type FROM tbl) x

Ini menghasilkan kueri yang sebenarnya Anda butuhkan. Jalankan yang kedua di dalam transaksi yang sama untuk menghindari masalah konkurensi.

Perhatikan penggunaan strategis quote_literal() dan quote_ident() untuk membersihkan semua jenis nama ilegal (untuk kolom) dan mencegah injeksi SQL .

Jangan bingung dengan beberapa lapisan kutipan dolar. Itu diperlukan untuk membangun kueri dinamis. Saya membuatnya sesederhana mungkin.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Pergi dan IN klausa di Postgres

  2. Hibernate + PostgreSQL + Jenis Alamat Jaringan (inet, cdir)

  3. Mengimpor file .sql di windows ke postgresql

  4. java.lang.ClassNotFoundException:org.postgresql.Driver

  5. Dapatkan Jumlah Hari dalam Sebulan di PostgreSQL