Du er ikke , faktisk ved at bruge aggregerede funktioner. Du bruger vinduefunktioner . Det er derfor PostgreSQL kræver sp.payout
og s.buyin
skal inkluderes i GROUP BY
klausul.
Ved at tilføje en OVER
klausul, den samlede funktion sum()
omdannes til en vinduesfunktion, som samler værdier pr. partition, mens den beholder alle rækker.
Du kan kombinere vinduesfunktioner og aggregerede funktioner . Aggregeringer anvendes først. Jeg forstod ikke ud fra din beskrivelse, hvordan du vil håndtere flere udbetalinger/indkøb pr. begivenhed. Som et gæt beregner jeg en sum af dem pr. begivenhed. Nu Jeg kan fjerne sp.payout
og s.buyin
fra GROUP BY
klausul og få en række pr. player
og 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 dette udtryk:sum(sum(sp.payout)) OVER w
, den ydre sum()
er en vinduesfunktion, den indre sum()
er en aggregeret funktion.
Forudsat p.player_id
og e.event_id
er PRIMARY KEY
i deres respektive tabeller.
Jeg tilføjede e.event_id
til ORDER BY
af WINDOW
klausul for at nå frem til en deterministisk sorteringsrækkefølge. (Der kan være flere begivenheder på samme dato.) Inkluderede også event_id
i resultatet for at skelne mellem flere begivenheder pr. dag.
Mens forespørgslen begrænser sig til en enkelt afspiller (WHERE p.player_id = 17
), behøver vi ikke tilføje p.name
eller p.player_id
til GROUP BY
og ORDER BY
. Hvis en af joinforbindelserne ville gange rækker unødigt, ville den resulterende sum være forkert (delvist eller fuldstændig ganget). Gruppering efter p.name
kunne ikke reparere forespørgslen derefter.
Jeg fjernede også e.date
fra GROUP BY
klausul. Den primære nøgle e.event_id
dækker alle kolonner i inputrækken siden PostgreSQL 9.1.
Hvis du ændrer forespørgslen for at returnere flere spillere på én gang, tilpasse:
...
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;
Medmindre p.name
er defineret unikt (?), gruppe og rækkefølge efter player_id
desuden for at få korrekte resultater i en deterministisk sorteringsrækkefølge.
Jeg beholdt kun e.date
og p.name
i GROUP BY
at have identisk sorteringsrækkefølge i alle klausuler, i håb om en præstationsfordel. Ellers kan du fjerne kolonnerne der. (Tilsvarende for kun e.date
i den første forespørgsel.)