Du bist nicht , tatsächlich unter Verwendung von Aggregatfunktionen. Sie verwenden Fensterfunktionen . Deshalb verlangt PostgreSQL sp.payout und s.buyin in GROUP BY einzuschließen Klausel.
Durch Anhängen eines OVER -Klausel, die Aggregatfunktion sum() wird in eine Fensterfunktion umgewandelt, die Werte pro Partition aggregiert und dabei behält alle Zeilen.
Sie können Fensterfunktionen und Aggregatfunktionen kombinieren . Aggregationen werden zuerst angewendet. Ich habe aus Ihrer Beschreibung nicht verstanden, wie Sie mit mehreren Auszahlungen / Buy-Ins pro Ereignis umgehen möchten. Als Schätzung berechne ich eine Summe davon pro Ereignis. Jetzt Ich kann sp.payout entfernen und s.buyin aus GROUP BY -Klausel und erhalte eine Zeile pro player und 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 diesem Ausdruck:sum(sum(sp.payout)) OVER w , die äußere sum() ist eine Fensterfunktion, die innere sum() ist eine Aggregatfunktion.
Angenommen p.player_id und e.event_id sind PRIMARY KEY in den jeweiligen Tabellen.
Ich habe e.event_id hinzugefügt zum ORDER BY des WINDOW -Klausel, um zu einer deterministischen Sortierreihenfolge zu gelangen. (Es können mehrere Ereignisse am selben Datum stattfinden.) Ebenfalls enthalten:event_id im Ergebnis, um mehrere Ereignisse pro Tag zu unterscheiden.
Während sich die Abfrage auf eine einzelne beschränkt Spieler (WHERE p.player_id = 17 ), müssen wir p.name nicht hinzufügen oder p.player_id zu GROUP BY und ORDER BY . Wenn einer der Joins Zeilen übermäßig multiplizieren würde, wäre die resultierende Summe falsch (teilweise oder vollständig multipliziert). Gruppierung nach p.name konnte die Abfrage dann nicht reparieren.
Ich habe auch e.date entfernt aus GROUP BY Klausel. Der Primärschlüssel e.event_id deckt alle Spalten der Eingabezeile seit PostgreSQL 9.1 ab.
Wenn Wenn Sie die Abfrage ändern, um mehrere Spieler gleichzeitig zurückzugeben, passen Sie Folgendes an:
...
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;
Außer p.name ist eindeutig (?) definiert, gruppiert und sortiert nach player_id zusätzlich um korrekte Ergebnisse in einer deterministischen Sortierreihenfolge zu erhalten.
Ich habe nur e.date beibehalten und p.name in GROUP BY identische Sortierreihenfolge in allen Klauseln zu haben, in der Hoffnung auf einen Leistungsvorteil. Andernfalls können Sie die Spalten dort entfernen. (Ähnlich für nur e.date in der ersten Abfrage.)