Iya. Dengan fungsi jendela sederhana:
SELECT *, count(*) OVER() AS full_count
FROM tbl
WHERE
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 dengan cara apa pun, yang membebankan biaya tergantung pada jumlah total baris yang memenuhi syarat. Rincian:
Namun , seperti yang ditunjukkan Dani , bila OFFSET
setidaknya sama banyaknya dengan jumlah baris yang dikembalikan dari kueri dasar, tidak ada baris yang dikembalikan. Jadi kami juga tidak mengerti full_count
.
Jika itu tidak dapat diterima, solusi yang mungkin untuk selalu mengembalikan hitungan penuh adalah dengan CTE dan OUTER JOIN
:
WITH cte AS (
SELECT *
FROM tbl
WHERE
)
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
penambahan jika OFFSET
terlalu besar. Lain, itu ditambahkan ke setiap baris seperti di kueri pertama.
Jika baris dengan semua nilai NULL adalah kemungkinan hasil yang valid, Anda harus memeriksa offset >= full_count
untuk menghilangkan keraguan 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 hitungan.
Jika indeks yang mendukung tata urutan akhir tersedia, mungkin ada baiknya untuk menyertakan ORDER BY
dalam CTE (secara berlebihan).