Du är inte , faktiskt med hjälp av aggregerade funktioner. Du använder fönsterfunktioner . Det är därför PostgreSQL kräver sp.payout
och s.buyin
inkluderas i GROUP BY
klausul.
Genom att lägga till en OVER
sats, den aggregerade funktionen sum()
förvandlas till en fönsterfunktion, som aggregerar värden per partition medan den behålls alla rader.
Du kan kombinera fönsterfunktioner och aggregerade funktioner . Aggregeringar tillämpas först. Jag förstod inte av din beskrivning hur du vill hantera flera utbetalningar/inköp per event. Som en gissning räknar jag ut en summa av dem per händelse. Nu Jag kan ta bort sp.payout
och s.buyin
från GROUP BY
och få en rad per player
och 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;
I detta uttryck:sum(sum(sp.payout)) OVER w
, den yttre sum()
är en fönsterfunktion, den inre sum()
är en aggregerad funktion.
Förutsatt p.player_id
och e.event_id
är PRIMARY KEY
i sina respektive tabeller.
Jag lade till e.event_id
till ORDER BY
i WINDOW
klausul för att komma fram till en deterministisk sorteringsordning. (Det kan finnas flera händelser på samma datum.) Inkluderade även event_id
i resultatet för att särskilja flera händelser per dag.
Medan frågan begränsas till en enkel spelare (WHERE p.player_id = 17
), behöver vi inte lägga till p.name
eller p.player_id
till GROUP BY
och ORDER BY
. Om en av kopplingarna skulle multiplicera rader i onödan, skulle den resulterande summan bli felaktig (delvis eller helt multiplicerad). Gruppering efter p.name
kunde inte reparera frågan då.
Jag tog också bort e.date
från GROUP BY
klausul. Den primära nyckeln e.event_id
täcker alla kolumner i inmatningsraden sedan PostgreSQL 9.1.
Om du ändrar frågan för att returnera flera spelare samtidigt, anpassa:
...
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;
Såvida inte p.name
definieras unikt (?), grupp och ordning efter player_id
dessutom för att få korrekta resultat i en deterministisk sorteringsordning.
Jag behöll bara e.date
och p.name
i GROUP BY
att ha identisk sorteringsordning i alla klausuler, i hopp om en prestationsfördel. Annars kan du ta bort kolumnerna där. (Liknande för bara e.date
i den första frågan.)