Ya. Dengan fungsi jendela sederhana:
SELECT *, count(*) OVER() AS full_count
FROM tbl
WHERE /* whatever */
ORDER BY col1
OFFSET ?
LIMIT ?
Ketahuilah bahwa biayanya akan jauh lebih tinggi daripada tanpa jumlah total, tetapi biasanya masih lebih murah daripada dua kueri terpisah. Postgres harus benar-benar menghitung semua baris cara mana pun, yang membebankan biaya tergantung pada jumlah total baris yang memenuhi syarat. Detail:
- Cara terbaik untuk mendapatkan jumlah hasil sebelum LIMIT diterapkan
Namun , seperti yang ditunjukkan Dani, ketika OFFSET
setidaknya sama besarnya dengan jumlah baris yang dikembalikan dari kueri dasar, tidak ada baris yang dikembalikan. Jadi kami juga tidak mendapatkan full_count
.
Jika itu tidak dapat diterima, kemungkinan solusi untuk selalu mengembalikan jumlah penuh akan dengan CTE dan OUTER JOIN
:
WITH cte AS (
SELECT *
FROM tbl
WHERE /* whatever */
)
SELECT *
FROM (
TABLE cte
ORDER BY col1
LIMIT ?
OFFSET ?
) sub
RIGHT JOIN (SELECT count(*) FROM cte) c(full_count) ON true;
Anda mendapatkan satu baris nilai NULL dengan full_count
ditambahkan jika OFFSET
terlalu besar. Jika tidak, itu ditambahkan ke setiap baris seperti pada kueri pertama.
Jika baris dengan semua nilai NULL adalah kemungkinan hasil yang valid, Anda harus memeriksa offset >= full_count
untuk membedakan asal baris kosong.
Ini masih mengeksekusi kueri dasar hanya sekali. Tapi itu menambahkan lebih banyak overhead ke kueri dan hanya membayar jika itu kurang dari mengulangi kueri dasar untuk penghitungan.
Jika indeks yang mendukung urutan pengurutan akhir tersedia, mungkin perlu menyertakan ORDER BY
di CTE (secara berlebihan).