Tu sei non , infatti, utilizzando funzioni aggregate. Stai utilizzando funzioni finestra . Ecco perché PostgreSQL richiede sp.payout e s.buyin da inserire nel GROUP BY clausola.
Aggiungendo un OVER clausola, la funzione aggregata sum() viene trasformato in una funzione finestra, che aggrega i valori per partizione mentre mantiene tutte le righe.
Puoi combinare le funzioni della finestra e aggregare le funzioni . Le aggregazioni vengono applicate per prime. Non ho capito dalla tua descrizione come vuoi gestire più pagamenti/acquisti per evento. A titolo di ipotesi, ne calcolo una somma per evento. Ora Posso rimuovere sp.payout e s.buyin dal GROUP BY clausola e ottieni una riga per player e 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;
In questa espressione:sum(sum(sp.payout)) OVER w , il sum() esterno è una funzione della finestra, il sum() interno è una funzione aggregata.
Supponendo p.player_id e e.event_id sono PRIMARY KEY nelle rispettive tabelle.
Ho aggiunto e.event_id al ORDER BY della WINDOW clausola per arrivare a un ordinamento deterministico. (Potrebbero esserci più eventi nella stessa data.) Includeva anche event_id nel risultato per distinguere più eventi al giorno.
Mentre la query si limita a un singolo giocatore (WHERE p.player_id = 17 ), non è necessario aggiungere p.name o p.player_id a GROUP BY e ORDER BY . Se uno dei join moltiplichi le righe indebitamente, la somma risultante sarebbe errata (moltiplicata in parte o completamente). Raggruppamento per p.name non è stato possibile riparare la query in quel momento.
Ho anche rimosso e.date dal GROUP BY clausola. La chiave primaria e.event_id copre tutte le colonne della riga di input da PostgreSQL 9.1.
Se cambi la query per restituire più giocatori contemporaneamente, adatta:
...
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;
A meno che p.name è definito unico (?), raggruppa e ordina per player_id inoltre per ottenere risultati corretti in un ordinamento deterministico.
Ho mantenuto solo e.date e p.name in GROUP BY avere un ordinamento identico in tutte le clausole, sperando in un vantaggio in termini di prestazioni. Altrimenti, puoi rimuovere le colonne lì. (Simile solo per e.date nella prima query.)