Oui. Avec une simple fonction de fenêtre:
SELECT *, count(*) OVER() AS full_count
FROM tbl
WHERE
ORDER BY col1
OFFSET ?
LIMIT ?
Sachez que le coût sera nettement plus élevé que sans le nombre total, mais généralement encore moins cher que deux requêtes distinctes. Postgres doit en fait compter toutes les lignes de toute façon, ce qui impose un coût dépendant du nombre total de lignes éligibles. Détails:
Cependant , comme l'a souligné Dani , lorsque OFFSET
est au moins aussi grand que le nombre de lignes renvoyées par la requête de base, aucune ligne n'est renvoyée. Donc nous n'obtenons pas non plus full_count
.
Si ce n'est pas acceptable, une solution de contournement possible pour toujours renvoyer le nombre complet serait avec un CTE et 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;
Vous obtenez une ligne de valeurs NULL avec le full_count
si ajouté OFFSET
est trop grand. Sinon, il est ajouté à chaque ligne comme dans la première requête.
Si une ligne avec toutes les valeurs NULL est un résultat valide possible, vous devez vérifier offset >= full_count
pour lever l'ambiguïté de l'origine de la ligne vide.
Cela n'exécute toujours la requête de base qu'une seule fois. Mais cela ajoute plus de surcharge à la requête et ne paie que si c'est moins que de répéter la requête de base pour le nombre.
Si des index prenant en charge l'ordre de tri final sont disponibles, il peut être payant d'inclure le ORDER BY
dans le CTE (de manière redondante).