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