Um das Ergebnis ohne Unterabfrage zu erhalten , müssen Sie auf fortgeschrittene Fensterfunktionstricks zurückgreifen:
SELECT sum(count(*)) OVER () AS tickets_count
, sum(min(a.revenue)) OVER () AS atendees_revenue
FROM tickets t
JOIN attendees a ON a.id = t.attendee_id
GROUP BY t.attendee_id
LIMIT 1;
sqlfiddle
Wie funktioniert es?
Der Schlüssel zum Verständnis ist die Reihenfolge der Ereignisse in der Abfrage:
Aggregatfunktionen -> Fensterfunktionen -> DISTINCT -> LIMIT
Weitere Einzelheiten:
- Bester Weg, um die Ergebnisanzahl zu erhalten, bevor LIMIT angewendet wurde
Schritt für Schritt:
-
I
GROUP BY t.attendee_id
- was Sie normalerweise in einer Unterabfrage tun würden. -
Dann summiere ich die Zählungen, um die Gesamtzahl der Tickets zu erhalten. Nicht sehr effizient, aber durch Ihre Anforderung gezwungen. Die Aggregatfunktion
count(*)
wird in die Fensterfunktionsum( ... ) OVER ()
eingeschlossen um zu dem nicht ganz so gebräuchlichen Ausdruck zu kommen:sum(count(*)) OVER ()
.Und addieren Sie den Mindestumsatz pro Teilnehmer, um die Summe ohne Duplikate zu erhalten.
Sie könnten auch
max()
verwenden oderavg()
stattmin()
mit der gleichen Wirkung wierevenue
ist garantiert für jede Zeile pro Teilnehmer gleich.Dies könnte einfacher sein, wenn
DISTINCT
war in Fensterfunktionen erlaubt, aber PostgreSQL hat diese Funktion (noch) nicht implementiert. Per Dokumentation:Aggregatfensterfunktionen erlauben im Gegensatz zu normalen Aggregatfunktionen
DISTINCT
nicht oderORDER BY
innerhalb der Funktionsargumentliste verwendet werden. -
Der letzte Schritt besteht darin, eine einzelne Zeile zu erhalten. Dies könnte mit
DISTINCT
erfolgen (SQL-Standard), da alle Zeilen gleich sind.LIMIT 1
wird aber schneller. Oder die SQL-StandardformFETCH FIRST 1 ROWS ONLY
.