Nie jesteś nie w rzeczywistości przy użyciu funkcji agregujących. Używasz funkcji okien . Dlatego PostgreSQL wymaga sp.payout
i s.buyin
do uwzględnienia w GROUP BY
klauzula.
Dołączając OVER
klauzula, funkcja agregująca sum()
jest przekształcany w funkcję okna, która agreguje wartości na partycję, jednocześnie zachowując wszystkie wiersze.
Możesz łączyć funkcje okna i funkcje agregujące . Agregacje są stosowane jako pierwsze. Z twojego opisu nie zrozumiałem, jak chcesz obsłużyć wielokrotne wypłaty / wpisowe na wydarzenie. Zgaduję, że obliczam ich sumę na wydarzenie. Teraz Mogę usunąć sp.payout
i s.buyin
z GROUP BY
klauzula i uzyskaj jeden wiersz na player
i 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;
W tym wyrażeniu:sum(sum(sp.payout)) OVER w
, zewnętrzna sum()
to funkcja okna, wewnętrzna sum()
jest funkcją agregującą.
Zakładając p.player_id
i e.event_id
to PRIMARY KEY
w odpowiednich tabelach.
Dodałem e.event_id
do ORDER BY
WINDOW
klauzula, aby uzyskać deterministyczny porządek sortowania. (Może być wiele wydarzeń tego samego dnia.) Uwzględniono także event_id
w rezultacie, aby rozróżnić wiele wydarzeń dziennie.
Podczas gdy zapytanie ogranicza się do jednego gracz (WHERE p.player_id = 17
), nie musimy dodawać p.name
lub p.player_id
do GROUP BY
i ORDER BY
. Gdyby jedno z połączeń niepotrzebnie mnożyło wiersze, suma wynikowa byłaby nieprawidłowa (pomnożona częściowo lub całkowicie). Grupowanie według p.name
nie mógł wtedy naprawić zapytania.
Usunąłem też e.date
z GROUP BY
klauzula. Klucz podstawowy e.event_id
obejmuje wszystkie kolumny wiersza wejściowego od wersji PostgreSQL 9.1.
Jeśli zmieniasz zapytanie, aby zwrócić wielu graczy naraz, dostosuj:
...
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;
Chyba że p.name
jest zdefiniowany jako unikalny (?), grupowany i uporządkowany według player_id
dodatkowo, aby uzyskać poprawne wyniki w deterministycznej kolejności sortowania.
Zachowałem tylko e.date
i p.name
w GROUP BY
mieć identyczną kolejność sortowania we wszystkich klauzulach, mając nadzieję na poprawę wydajności. W przeciwnym razie możesz usunąć tam kolumny. (Podobne tylko dla e.date
w pierwszym zapytaniu).