Có. Với một chức năng cửa sổ đơn giản:
SELECT *, count(*) OVER() AS full_count
FROM tbl
WHERE /* whatever */
ORDER BY col1
OFFSET ?
LIMIT ?
Lưu ý rằng chi phí sẽ cao hơn đáng kể so với khi không có tổng số, nhưng thường vẫn rẻ hơn so với hai truy vấn riêng biệt. Postgres thực sự phải đếm tất cả các hàng một trong hai cách sẽ áp dụng chi phí tùy thuộc vào tổng số hàng đủ điều kiện. Chi tiết:
- Cách tốt nhất để tính kết quả trước khi LIMIT được áp dụng
Tuy nhiên , như Dani đã chỉ ra, khi OFFSET
ít nhất là lớn bằng số hàng được trả về từ truy vấn cơ sở, không có hàng nào được trả lại. Vì vậy, chúng tôi cũng không nhận được full_count
.
Nếu điều đó không được chấp nhận, một giải pháp khả thi để luôn trả lại tổng số đầy đủ sẽ có CTE và 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;
Bạn nhận được một hàng giá trị NULL với full_count
thêm vào nếu OFFSET
to quá. Mặt khác, nó được thêm vào mọi hàng như trong truy vấn đầu tiên.
Nếu một hàng có tất cả các giá trị NULL là kết quả hợp lệ có thể có, bạn phải kiểm tra offset >= full_count
để phân biệt nguồn gốc của hàng trống.
Điều này vẫn thực hiện truy vấn cơ sở chỉ một lần. Nhưng nó thêm nhiều chi phí hơn cho truy vấn và chỉ trả tiền nếu điều đó ít hơn việc lặp lại truy vấn cơ sở cho số lượng.
Nếu các chỉ mục hỗ trợ thứ tự sắp xếp cuối cùng có sẵn, thì có thể trả tiền để bao gồm ORDER BY
trong CTE (dư thừa).