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.)