For at få resultatet uden underforespørgsel , skal du ty til avanceret vinduesfunktionstrickeri:
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
Hvordan fungerer det?
Nøglen til at forstå dette er rækkefølgen af begivenheder i forespørgslen:
aggregerede funktioner -> vinduesfunktioner -> DISTINCT -> LIMIT
Flere detaljer:
- Bedste måde at få resultattælling, før LIMIT blev anvendt
Trin for trin:
-
Jeg
GROUP BY t.attendee_id- hvilket du normalt ville gøre i en underforespørgsel. -
Så summerer jeg optællingerne for at få det samlede antal billetter. Ikke særlig effektiv, men tvunget af dit krav. Den samlede funktion
count(*)er pakket ind i vinduesfunktionensum( ... ) OVER ()for at nå frem til det ikke så almindelige udtryk:sum(count(*)) OVER ().Og summer minimumsindtægten pr. deltager for at få summen uden dubletter.
Du kan også bruge
max()elleravg()i stedet formin()til samme effekt somrevenueer garanteret den samme for hver række pr. deltager.Dette kunne være enklere, hvis
DISTINCTvar tilladt i vinduesfunktioner, men PostgreSQL har (endnu) ikke implementeret denne funktion. Per dokumentation:Aggregerede vinduesfunktioner tillader i modsætning til normale aggregerede funktioner ikke
DISTINCTellerORDER BYskal bruges i funktionsargumentlisten. -
Sidste trin er at få en enkelt række. Dette kunne gøres med
DISTINCT(SQL-standard), da alle rækker er ens.LIMIT 1vil dog være hurtigere. Eller SQL-standardformenFETCH FIRST 1 ROWS ONLY.