Sí. Con una función de ventana simple:
SELECT *, count(*) OVER() AS full_count
FROM tbl
WHERE /* whatever */
ORDER BY col1
OFFSET ?
LIMIT ?
Tenga en cuenta que el costo será sustancialmente más alto que sin el número total, pero por lo general aún 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:
- La mejor manera de obtener el recuento de resultados antes de aplicar LIMIT
Sin embargo , como señaló Dani, cuando OFFSET
es al menos tan grande como el número de filas devueltas por la consulta base, no se devuelve ninguna fila. Así que tampoco obtenemos full_count
.
Si eso no es aceptable, una posible solución alternativa para devolver siempre el recuento completo sería con un CTE y un 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;
Obtiene una fila de valores NULL con full_count
adjunto si OFFSET
es demasiado grande. De lo contrario, se adjunta a cada fila como en la primera consulta.
Si una fila con todos los valores NULL es un posible resultado válido, debe marcar 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 es menos que repetir la consulta base para el conteo.
Si los índices que admiten el orden de clasificación final están disponibles, podría ser conveniente incluir el ORDER BY
en el CTE (redundantemente).