Aby uzyskać wynik bez podzapytania , musisz uciec się do zaawansowanych sztuczek funkcji okna:
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
Jak to działa?
Kluczem do zrozumienia tego jest sekwencja wydarzeń w zapytaniu:
funkcje agregujące -> funkcje okien -> DISTINCT -> LIMIT
Więcej szczegółów:
- Najlepszy sposób na uzyskanie liczby wyników przed zastosowaniem LIMITu
Krok po kroku:
-
I
GROUP BY t.attendee_id
- co normalnie zrobiłbyś w podzapytaniu. -
Następnie sumuję liczniki, aby uzyskać całkowitą liczbę biletów. Niezbyt wydajny, ale wymuszony przez twoje wymagania. Funkcja agregująca
count(*)
jest opakowany w funkcję oknasum( ... ) OVER ()
aby dojść do niezbyt powszechnego wyrażenia:sum(count(*)) OVER ()
.I zsumuj minimalny przychód na uczestnika, aby otrzymać sumę bez duplikatów.
Możesz także użyć
max()
lubavg()
zamiastmin()
działa tak samo jakrevenue
gwarantuje, że będzie taki sam dla każdego wiersza na uczestnika.Może to być prostsze, jeśli
DISTINCT
było dozwolone w funkcjach okien, ale PostgreSQL nie zaimplementował (jeszcze) tej funkcji. Zgodnie z dokumentacją:Funkcje okna agregującego, w przeciwieństwie do normalnych funkcji agregujących, nie pozwalają na
DISTINCT
lubORDER BY
do użycia na liście argumentów funkcji. -
Ostatnim krokiem jest uzyskanie jednego rzędu. Można to zrobić za pomocą
DISTINCT
(standard SQL), ponieważ wszystkie wiersze są takie same.LIMIT 1
będzie jednak szybszy. Lub standardowy formularz SQLFETCH FIRST 1 ROWS ONLY
.