Untuk mendapatkan hasil tanpa subquery , Anda harus menggunakan tipuan fungsi jendela tingkat lanjut:
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
Bagaimana cara kerjanya?
Kunci untuk memahami ini adalah urutan peristiwa dalam kueri:
fungsi agregat -> fungsi jendela -> DISTINCT -> LIMIT
Selengkapnya:
- Cara terbaik untuk mendapatkan jumlah hasil sebelum LIMIT diterapkan
Langkah demi langkah:
-
Saya
GROUP BY t.attendee_id
- yang biasanya Anda lakukan dalam subkueri. -
Kemudian saya menjumlahkan hitungan untuk mendapatkan jumlah total tiket. Tidak terlalu efisien, tetapi dipaksa oleh kebutuhan Anda. Fungsi agregat
count(*)
dibungkus dalam fungsi jendelasum( ... ) OVER ()
untuk sampai pada ekspresi yang tidak terlalu umum:sum(count(*)) OVER ()
.Dan jumlahkan pendapatan minimum per peserta untuk mendapatkan jumlah tanpa duplikat.
Anda juga dapat menggunakan
max()
atauavg()
bukannyamin()
dengan efek yang sama sepertirevenue
dijamin sama untuk setiap baris per peserta.Ini bisa lebih sederhana jika
DISTINCT
diizinkan di fungsi jendela, tetapi PostgreSQL belum (belum) mengimplementasikan fitur ini. Per dokumentasi:Fungsi jendela agregat, tidak seperti fungsi agregat normal, tidak mengizinkan
DISTINCT
atauORDER BY
untuk digunakan dalam daftar argumen fungsi. -
Langkah terakhir adalah mendapatkan satu baris. Ini dapat dilakukan dengan
DISTINCT
(Standar SQL) karena semua baris sama.LIMIT 1
akan lebih cepat, meskipun. Atau formulir standar SQLFETCH FIRST 1 ROWS ONLY
.