sql >> Base de Datos >  >> RDS >> PostgreSQL

Ejecute una consulta con LIMIT/OFFSET y también obtenga el número total de filas

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).