Si. Con una función de ventana simple:
SELECT *, count(*) OVER() AS full_count
FROM tbl
WHERE
ORDER BY col1
OFFSET ?
LIMIT ?
Tenga en cuenta que el costo será sustancialmente más alto que sin el número total, pero generalmente más económico que dos consultas separadas. Postgres tiene que contar todas las filas de cualquier manera, lo que impone un costo que depende del número total de filas calificadas. Detalles:
Sin embargo , como señaló Dani , cuando OFFSET
es al menos tan grande como el número de filas devueltas de la consulta base, no se devuelven filas. Entonces tampoco lo conseguimos full_count
.
Si eso no es aceptable, una posible solución para devolver siempre el recuento completo sería con un CTE y un 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;
Obtiene una fila de valores NULL con el full_count
if adjunto OFFSET
es demasiado grande. De lo contrario, se agrega a cada fila como en la primera consulta.
Si una fila con todos los valores NULL es un posible resultado válido, debe verificar offset >= full_count
para eliminar la ambigüedad del origen de la fila vacía.
Esto aún ejecuta la consulta base solo una vez. Pero agrega más gastos generales a la consulta y solo paga si eso es menos que repetir la consulta base para el recuento.
Si los índices que soportan el orden de clasificación final están disponibles, podría ser útil incluirlos ORDER BY
en el CTE (de forma redundante).