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).