Đúng. Với một chức năng cửa sổ đơn giản:
SELECT *, count(*) OVER() AS full_count
FROM tbl
WHERE
ORDER BY col1
OFFSET ?
LIMIT ?
Lưu ý rằng chi phí sẽ cao hơn đáng kể so với 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 theo cả hai cách, điều này áp đặt chi phí tùy thuộc vào tổng số hàng đủ điều kiện. Chi tiết:
Tuy nhiên , như Dani đã chỉ ra , khi OFFSET
ít nhất bằng số hàng được trả về từ truy vấn cơ sở, không có hàng nào được trả về. 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ả về tổng số đầy đủ sẽ là với CTE và 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;
Bạn nhận được một hàng giá trị NULL với full_count
thêm nếu OFFSET
quá lớn. 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à một 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 vào 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, bạn có thể phải trả tiền để đưa ORDER BY
vào CTE (dự phòng).