nejste ve skutečnosti pomocí agregačních funkcí. Používáte funkce oken . To je důvod, proč PostgreSQL požaduje sp.payout
a s.buyin
být zahrnut do GROUP BY
doložka.
Připojením OVER
klauzule, agregační funkce sum()
se změní na funkci okna, která agreguje hodnoty na oddíl a přitom zachovává všechny řádky.
Můžete kombinovat funkce okna a agregační funkce . Nejprve se použijí agregace. Z vašeho popisu jsem nepochopil, jak chcete zacházet s více výplatami / buyiny za událost. Odhadem vypočítám jejich součet na událost. Nyní Mohu odstranit sp.payout
a s.buyin
z GROUP BY
klauzule a získáte jeden řádek na player
a 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;
V tomto výrazu:sum(sum(sp.payout)) OVER w
, vnější sum()
je funkce okna, vnitřní sum()
je agregační funkce.
Za předpokladu p.player_id
a e.event_id
jsou PRIMARY KEY
v příslušných tabulkách.
Přidal jsem e.event_id
do ORDER BY
z WINDOW
klauzule k dosažení deterministického pořadí řazení. (Ve stejném datu může být více událostí.) Zahrnuje také event_id
ve výsledku rozlišit více událostí za den.
Zatímco dotaz se omezuje na jeden hráč (WHERE p.player_id = 17
), nemusíme přidávat p.name
nebo p.player_id
na GROUP BY
a ORDER BY
. Pokud by jedno ze spojení nepatřičně násobilo řádky, výsledný součet by byl nesprávný (částečně nebo úplně vynásobený). Seskupení podle p.name
nemohl poté dotaz opravit.
Také jsem odstranil e.date
z GROUP BY
doložka. Primární klíč e.event_id
pokrývá všechny sloupce vstupního řádku od PostgreSQL 9.1.
Pokud změníte dotaz tak, aby vracel více hráčů najednou, přizpůsobte:
...
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;
Pokud není p.name
je definována jedinečná (?), skupina a pořadí pomocí player_id
navíc získat správné výsledky v deterministickém pořadí řazení.
Ponechal jsem pouze e.date
a p.name
v GROUP BY
mít identické pořadí řazení ve všech klauzulích v naději na výkonnost. Jinak tam můžete sloupce odstranit. (Podobné pouze pro e.date
v prvním dotazu.)