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

Fungsi jendela Postgres dan kelompokkan dengan pengecualian

Anda tidak , pada kenyataannya, menggunakan fungsi agregat. Anda menggunakan fungsi jendela . Itulah mengapa PostgreSQL menuntut sp.payout dan s.buyin untuk dimasukkan dalam GROUP BY klausa.

Dengan menambahkan OVER klausa, fungsi agregat sum() diubah menjadi fungsi jendela, yang menggabungkan nilai per partisi sambil menjaga semua baris.

Anda dapat menggabungkan fungsi jendela dan fungsi agregat . Agregasi diterapkan terlebih dahulu. Saya tidak mengerti dari deskripsi Anda bagaimana Anda ingin menangani beberapa pembayaran / pembelian per acara. Sebagai tebakan, saya menghitung jumlah mereka per acara. Sekarang Saya dapat menghapus sp.payout dan s.buyin dari GROUP BY klausa dan dapatkan satu baris per player dan event :

SELECT p.name
     , e.event_id
     , e.date
     , sum(sum(sp.payout)) OVER w
     - sum(sum(s.buyin  )) OVER w AS "Profit/Loss" 
FROM   player            p
JOIN   result            r ON r.player_id     = p.player_id  
JOIN   game              g ON g.game_id       = r.game_id 
JOIN   event             e ON e.event_id      = g.event_id 
JOIN   structure         s ON s.structure_id  = g.structure_id 
JOIN   structure_payout sp ON sp.structure_id = g.structure_id
                          AND sp.position     = r.position
WHERE  p.player_id = 17 
GROUP  BY e.event_id
WINDOW w AS (ORDER BY e.date, e.event_id)
ORDER  BY e.date, e.event_id;

Dalam ekspresi ini:sum(sum(sp.payout)) OVER w , bagian luar sum() adalah fungsi jendela, bagian dalam sum() adalah fungsi agregat.

Dengan asumsi p.player_id dan e.event_id adalah PRIMARY KEY di tabel masing-masing.

Saya menambahkan e.event_id ke ORDER BY dari WINDOW klausa untuk sampai pada urutan pengurutan deterministik. (Mungkin ada beberapa acara pada tanggal yang sama.) Juga termasuk event_id dalam hasil untuk membedakan beberapa peristiwa per hari.

Sementara kueri terbatas pada tunggal pemain (WHERE p.player_id = 17 ), kita tidak perlu menambahkan p.name atau p.player_id ke GROUP BY dan ORDER BY . Jika salah satu gabungan akan mengalikan baris terlalu banyak, jumlah yang dihasilkan akan salah (sebagian atau seluruhnya dikalikan). Pengelompokan berdasarkan p.name tidak dapat memperbaiki kueri saat itu.

Saya juga menghapus e.date dari GROUP BY ayat. Kunci utama e.event_id mencakup semua kolom dari baris input sejak PostgreSQL 9.1.

Jika Anda mengubah kueri untuk mengembalikan beberapa pemain sekaligus, sesuaikan:

...
WHERE  p.player_id < 17  -- example - multiple players
GROUP  BY p.name, p.player_id, e.date, e.event_id  -- e.date and p.name redundant
WINDOW w AS (ORDER BY p.name, p.player_id, e.date, e.event_id)
ORDER  BY p.name, p.player_id, e.date, e.event_id;

Kecuali p.name didefinisikan unik (?), kelompokkan dan urutkan berdasarkan player_id tambahan untuk mendapatkan hasil yang benar dalam urutan pengurutan deterministik.

Saya hanya menyimpan e.date dan p.name di GROUP BY memiliki urutan pengurutan yang identik di semua klausa, dengan harapan mendapatkan manfaat kinerja. Jika tidak, Anda dapat menghapus kolom di sana. (Mirip dengan e.date dalam kueri pertama.)




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Nama Proses PostgreSQL di Solaris

  2. Instalasi PostgreSQL di Docker

  3. Array integer Postgres sebagai parameter?

  4. Bagaimana saya bisa memasukkan komentar kolom di PostgreSQL melalui Python?

  5. PSQLException:transaksi saat ini dibatalkan, perintah diabaikan hingga akhir blok transaksi