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.)